2016-09-07 86 views
0

我想通过重叠对时间组进行分组,但我无法弄清楚如何完全做到这一点。将可能没有直接重叠的多个重叠时间组分组

我在[{start_at: Date, end_at: Date, etc.etc. }]

形式非常简单的数组,我躺在出来,我认为这样的

<---slot1----><----slot5----><--slot6--> 
    <--slot2-><--slot4--->   <--slot7--> 
    <----slot3----> 

找到直接重叠插槽并不难,我只是一个比较插槽与下一个与(StartA <= EndB) and (EndA >= StartB) from here

现在我想分组我的重叠插槽(插槽1,2,3,4和5),但不包括插槽6和7,并将这两个插入到他们自己的组中。变成类似[[Slot (has 1 through 5)][Slot (has 6 and 7)]]

我有点迷失了这个问题,我希望这里有人能帮助我。

回答

1

我建议创建一个Slot对象保存:

  • 在插槽项目的array
  • 这些项目的最早日期start_at
  • 这些项目的最新end_at

通过保持最新的插槽范围,您不必将新项目与每个插槽项目进行比较。你只需要比较插槽本身。

现在,您必须按start_at排序项目。然后,您可以减少由数组:

  • 的第一个项目
  • 设置Slotstart_atend_at模仿者中的第一项
  • 转到第二个项目的创建Slot,检查与第一Slot
    • 如果重叠,
      • 推的S重叠的Econd项目的Slot的项目阵列,以及
      • 设置start_at到最小的Slot.start_atitem2.start_at
      • 做同样的(最大)end_at
    • 如果不重叠,
      • 为第二项创建新的Slot,以此重复Slotitem3(等等)

实现示例(我建议你根据你的个人喜好来重写。我没有做任何整齐的类/原型的/ etc。,我也没有测试它彻底)

function createSlot(initialItem) { 
 
var slot = { 
 
    items: [initialItem], 
 
    start: initialItem.start, 
 
    end: initialItem.end 
 
}; 
 
    
 
    slot.addItem = function(item) { 
 
    slot.items.push(item); 
 
    slot.start = Math.min(slot.start, item.start); 
 
    slot.end = Math.max(slot.end, item.end); 
 
    } 
 
    
 
    return slot; 
 
}; 
 
    
 
function itemsOverlap(item1, item2) { 
 
    return item1.start <= item2.end && 
 
    item1.end >= item2.start; 
 
}; 
 

 
var slots = []; 
 
var items = randomItems(10); 
 

 

 
items.slice(1).reduce(function(currentSlot, item) { 
 
    if (itemsOverlap(currentSlot, item)) { 
 
    currentSlot.addItem(item); 
 
    return currentSlot; 
 
    } 
 
    
 
    slots.push(currentSlot); 
 
    return createSlot(item); 
 
}, createSlot(items[0])); 
 

 
console.log(
 
    slots.map(function(slot) { return slot.items.length; })); 
 

 

 

 
// Create random data 
 
function randomItems(n) { 
 
    var arr = []; 
 
    for (var i = 0; i < n; i += 1) { 
 
    arr.push(generateRandomItem()); 
 
    } 
 
    return arr.sort(function(a, b) { return a.start - b.start; }); 
 
}; 
 

 

 
function randomHourTimespan() { 
 
    return Math.random() * 60 * 60 * 1000; 
 
}; 
 

 
function randomHalfDayTimespan() { 
 
    return randomHourTimespan() * 12; 
 
}; 
 

 
function generateRandomItem() { 
 
    var start = Date.now() + randomHalfDayTimespan(); 
 
    var end = start + randomHourTimespan(); 
 
    
 
    return { start: new Date(start), end: new Date(end) }; 
 
}

+0

谢谢!这对我帮助很大! –

0

我实现了一个简单的算法组的插槽关于向startend值。

这里是一个工作小提琴https://jsfiddle.net/LeoAref/gg6q0mby/,你会发现一个视觉呈现的分组。

var timeSlots = [ 
    {start: 0, end: 3}, 
    {start: 1, end: 2}, 
    {start: 2, end: 4}, 
    {start: 4, end: 6}, 
    {start: 4, end: 8}, 
    {start: 5, end: 6} 
]; 

timeSlots.forEach((slot, index) => { 
    var slotElem = document.createElement('div'); 

    slotElem.classList.add('slot'); 
    slotElem.style.top = index * 25 + 'px'; 
    slotElem.style.left = slot.start * 30 + 'px'; 
    slotElem.style.width = (slot.end - slot.start) * 30 + 'px'; 

    document.body.appendChild(slotElem); 
}); 

var groups = []; 

timeSlots.forEach(slot => { 
    added = false; 

    if (groups.length) { 
    var index = 0; 

    do { 
     group = groups[index]; 

     if (slot.start >= group.start && slot.start < group.end || 
      slot.end <= group.end && slot.end > group.start 
    ) { 
     group.slots.push(slot); 

     group.start = Math.min(slot.start, group.start); 
     group.end = Math.max(slot.end, group.end); 

     added = true; 
     } 
    } while (!added && ++index < groups.length); 

    if (!added) { 
     groups.push({start: slot.start, end: slot.end, slots: [slot]}); 
    } 
    } else { 
    groups.push({start: slot.start, end: slot.end, slots: [slot]}); 
    } 
}) 

groups.forEach(group => { 
    var groupElem = document.createElement('div'); 

    groupElem.classList.add('group'); 
    groupElem.style.left = group.start * 30 + 'px'; 
    groupElem.style.width = (group.end - group.start) * 30 - 2 + 'px'; 

    document.body.appendChild(groupElem); 
})