我正在研究人员配置应用程序。我们具有将员工转移到团队的功能。我想添加验证来检查用户是否已经预订了该特定时间段。例如,在下面的屏幕截图中,用户 mate 位置重叠。不能在同一时间将他分配到两个团队。
这个问题更多地与数据结构有关。我编写的代码似乎可以正常工作,但我仍然不确定,我相信它可以做得更好。就像没有运行两个循环?。
如果需要修改数据结构以获得更好的性能,也可以。
https://codesandbox.io/s/pj2kmz1kox
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>
);
}
}
答案 0 :(得分:1)
该演示包含class
,其中包含一些使用ES6 Map存储日期范围的方法。每个说明都代表员工的时间表。 OP没有提及如何处理重叠的日期,因此这是日期范围验证规则:
日期被转换为毫秒以进行比较(.getTime()
)
如果一个开始日期大于另一个开始日期并且小于其结束日期,则使用最早的开始日期,然后新的结束日期将是两个结束日期中的较大者。
如果输入开始日期大于输入结束日期,则会交换它们。
每个范围都由一个索引存储。
顺便说一句,日期是准确的,但格式各不相同,我将把它留给OP。
class schedule {
constructor(id) {
this.id = id;
this.index = 0;
this.map = new Map;
}
addSlot([startString, endString]) {
this.index = this.map.size;
let startDate = new Date(startString);
let endDate = new Date(endString);
let startTime = startDate.getTime();
let endTime = endDate.getTime()
if (startTime > endTime) {
let temp = endDate;
endDate = startDate;
startDate = temp;
}
if (this.map.size > 0) {
for (let [key, value] of this.map) {
let start = value[0].getTime();
let end = value[1].getTime();
let newStart = startTime > start && startTime < end ? value[0] : start > startTime && start < endTime ? startDate : false;
let newEnd;
if (newStart) {
newEnd = end > endTime ? value[1] : endDate;
this.map.set(key, [newStart, newEnd]);
} else {
this.map.set(this.index, [startDate, endDate]);
}
}
} else {
this.map.set(this.index, [startDate, endDate]);
}
}
hasSlot(index) {
return this.map.has(index);
}
getSlot(index) {
return this.map.get(index);
}
viewSlots() {
let list = '';
for (let [key, value] of this.map) {
list += `
${key}: [Start: ${value[0]} -
End: ${value[1]}]
`;
}
return list;
}
removeSlot(index) {
if (this.map.has(index)) {
this.map.delete(index);
} else {
return index + 'does not exist';
}
}
}
const m = new schedule('Mate');
console.log(m.id);
m.addSlot(['04/19/2019', '04/28/2019']);
console.log(m.hasSlot(0));
m.addSlot(['04/21/2019', '05/12/2019']);
console.log(m.hasSlot(1));
console.log(m.getSlot(0));
m.addSlot(['08/19/2019', '09/12/2019']);
console.log(m.hasSlot(1));
console.log(m.getSlot(1));
console.log(m.viewSlots());
答案 1 :(得分:0)
如果您对更有效的数据结构感兴趣,可以尝试在此处使用二叉树。将您的非重叠间隔放入该树中。
由于您对非重叠间隔感兴趣,因此您在它们上定义了自然顺序:间隔A>如果间隔A在时间轴上位于间隔B的右侧,则间隔B。
您可以一次又一次地添加间隔,以确保每个新间隔都不与现有间隔重叠。对于每个新间隔,它将花费O(log n)。如果编辑了一个间隔,则必须删除相应的节点并添加一个新的节点,当然要保持二叉树的结构。
但是实际上,您可能只有很少的时间间隔,因此使用复杂的数据结构没有任何意义。您只需使用简单的间隔列表并对其进行迭代,就可以了。