Javascript 检查用户是否已分配到特定插槽

Javascript 检查用户是否已分配到特定插槽,javascript,algorithm,data-structures,Javascript,Algorithm,Data Structures,我正在处理人员配置申请。我们有一个功能,可以将员工转移到团队中。我想添加验证,以检查用户是否已经预订了该特定时段。例如,在下面的屏幕截图中,用户mate插槽重叠。他不能在同一时间内被分配到两个队 这个问题更多的是关于数据结构的。我写的代码似乎很管用,但我对它没有信心,我相信它可以做得更好。比如不运行两个循环 如果我们需要修改数据结构以获得更好的性能,这是可以的 类应用程序扩展组件{ 状态={ selectedItem:{} }; updateDate=(索引,字段,{target:{valu

我正在处理人员配置申请。我们有一个功能,可以将员工转移到团队中。我想添加验证,以检查用户是否已经预订了该特定时段。例如,在下面的屏幕截图中,用户mate插槽重叠。他不能在同一时间内被分配到两个队

这个问题更多的是关于数据结构的。我写的代码似乎很管用,但我对它没有信心,我相信它可以做得更好。比如不运行两个循环

如果我们需要修改数据结构以获得更好的性能,这是可以的

类应用程序扩展组件{
状态={
selectedItem:{}
};
updateDate=(索引,字段,{target:{value}})=>{
const{selectedItem}=this.state;
const newSelectedItem={…selectedItem};
newSelectedItem[index]=newSelectedItem[index]|{
id:new Date().getTime()
};
newSelectedItem[索引][字段]=新日期(值);
这是我的国家({
selectedItem:newSelectedItem
});
此.valiateAvailability();
};
handleDropdown=(索引,{target:{value}})=>{
const{selectedItem}=this.state;
const newSelectedItem={…selectedItem};
newSelectedItem[index]=newSelectedItem[index]|{
id:new Date().getTime()
};
newSelectedItem[index][“userId”]=值;
这是我的国家({
selectedItem:newSelectedItem
});
此.valiateAvailability();
};
有效可用性=()=>{
const{selectedItem}=this.state;
常量错误={};
for(让我选择editem){
const userId=selectedItem[i].userId;
const id=selectedItem[i].id;
const from=selectedItem[i]。from;
const to=selectedItem[i]。to;
for(让z进入selectedItem){
const fromB=selectedItem[z]。from;
const toB=selectedItem[z]。to;
如果(userId==selectedItem[z].userId&&id!==selectedItem[z].id){
if(from=fromB){
错误[z]=“错误”;
}
}
}
}
console.log(“错误”,error);
};
render(){
console.log(this.state.selectedItem);
返回(
{[1,2,3]。地图((项目,索引)=>{
返回(
this.handleDropdown(索引,e)}>
选择用户
伴侣
比尔
this.updateDate(索引,“from”,e)}
/>
this.updateDate(索引“to”,e)}
/>
);
})}
);
}
}

此演示有一个
,其中包含一些使用ES6映射存储日期范围的方法。每个指令代表一名员工的日程安排。OP未提及如何处理重叠日期,因此以下是日期范围验证规则:

  • 将日期转换为毫秒进行比较(
    .getTime()

  • 如果开始日期大于另一个开始日期且小于其结束日期,则使用最早的开始日期,然后新的结束日期将是两个结束日期中的较大日期

  • 如果输入开始日期大于输入结束日期,则将交换这些日期

  • 每个范围由一个索引存储

顺便说一句,日期是准确的,但格式不同,我将留给OP决定

课程表{
建造师(id){
this.id=id;
该指数=0;
this.map=新地图;
}
addSlot([startString,endString]){
this.index=this.map.size;
让startDate=新日期(startString);
让endDate=新日期(endString);
让startTime=startDate.getTime();
让endTime=endDate.getTime()
如果(开始时间>结束时间){
设temp=endDate;
endDate=开始日期;
起始日期=温度;
}
如果(this.map.size>0){
for(让这个.map的[key,value]{
让start=value[0].getTime();
让end=value[1]。getTime();
让newStart=startTime>start&&startTimestartTime&&startendTime?值[1]:endDate;
this.map.set(键[newStart,newEnd]);
}否则{
this.map.set(this.index[startDate,endDate]);
}
}
}否则{
this.map.set(this.index[startDate,endDate]);
}
}
哈斯洛特(索引){
返回此.map.has(索引);
}
getSlot(索引){
返回此.map.get(索引);
}
viewSlots(){
让列表=“”;
for(让这个.map的[key,value]{
列表+=`
${key}:[开始:${value[0]}-
结束:${value[1]}]
`;
}
退货清单;
}
removeSlot(索引){
if(this.map.has(index)){
此.map.delete(索引);
}否则{
返回索引+'不存在';
}
}
}
常数m=新附表(“配合”);
控制台日志(m.id);
m、 添加插槽(['4/19/2019','4/28/2019']);
console.log(m.hasSlot(0));
m、 添加插槽(['04/21/2019','05/12/2019']);
控制台日志(m.hasSlot(1));
console.log(m.getSlot(0));
m、 添加插槽(['08/19/2019','09/12/2019']);
控制台日志(m.hasSlot(1));
console.log(m.getSlot(1));

log(m.viewSlots())如果您对更高效的数据结构感兴趣,可以尝试在此处使用二叉树。把不重叠的间隔放在树上

由于您对不重叠的间隔感兴趣,因此在它们上定义了一个自然顺序:如果a位于时间轴上B的右侧,则间隔a>间隔B

您可以逐个添加间隔,同时检查每个新间隔是否与现有间隔重叠。对于每一个新的间隔,都需要O(logn)。如果编辑了一个间隔,那么您必须删除相应的节点并添加一个新节点,当然要保留二叉树结构

然而,在实践中,你可能会有少量的间隔,而且确实如此
class App extends Component {
  state = {
    selectedItem: {}
  };
  updateDate = (index, field, { target: { value } }) => {
    const { selectedItem } = this.state;
    const newSelectedItem = { ...selectedItem };
    newSelectedItem[index] = newSelectedItem[index] || {
      id: new Date().getTime()
    };
    newSelectedItem[index][field] = new Date(value);
    this.setState({
      selectedItem: newSelectedItem
    });
    this.valiateAvailibility();
  };

  handleDropdown = (index, { target: { value } }) => {
    const { selectedItem } = this.state;
    const newSelectedItem = { ...selectedItem };
    newSelectedItem[index] = newSelectedItem[index] || {
      id: new Date().getTime()
    };
    newSelectedItem[index]["userId"] = value;
    this.setState({
      selectedItem: newSelectedItem
    });
    this.valiateAvailibility();
  };

  valiateAvailibility = () => {
    const { selectedItem } = this.state;
    const error = {};
    for (let i in selectedItem) {
      const userId = selectedItem[i].userId;
      const id = selectedItem[i].id;
      const from = selectedItem[i].from;
      const to = selectedItem[i].to;
      for (let z in selectedItem) {
        const fromB = selectedItem[z].from;
        const toB = selectedItem[z].to;
        if (userId == selectedItem[z].userId && id !== selectedItem[z].id) {
          if (from <= toB && to >= fromB) {
            error[z] = "error";
          }
        }
      }
    }
    console.log("error", error);
  };

  render() {
    console.log(this.state.selectedItem);
    return (
      <div className="App">
        {[1, 2, 3].map((item, index) => {
          return (
            <div>
              <select onChange={e => this.handleDropdown(index, e)}>
                <option>Select User</option>
                <option value="12">Mate</option>
                <option value="23">Bill</option>
              </select>
              <input
                type="date"
                onChange={e => this.updateDate(index, "from", e)}
              />
              <input
                type="date"
                onChange={e => this.updateDate(index, "to", e)}
              />
            </div>
          );
        })}
      </div>
    );
  }
}