简体   繁体   English

计算对象数组中重叠日期的最大数量

[英]Count maximum number of overlapping dates within array of objects

If I have the following array of objects with start and end dates, how can I best calculate the maximum number of ranges that overlap each other?如果我有以下具有开始日期和结束日期的对象数组,我怎样才能最好地计算相互重叠的最大范围数? I just want the count for the highest number of overlapping ranges.我只想要最大数量的重叠范围的计数。 eg my example below the highest number of overlapping ranges would be 3.例如,我在最大重叠范围下方的示例是 3。

[
  { start_date: '2021-01-01 10:00:00', end_date: '2021-01-01 11:00:00'},
  { start_date: '2021-01-01 08:00:00', end_date: '2021-01-01 11:00:00'},
  { start_date: '2021-01-01 12:00:00', end_date: '2021-01-01 14:00:00'},
  { start_date: '2021-01-01 12:30:00', end_date: '2021-01-01 14:30:00'},
  { start_date: '2021-01-01 14:00:00', end_date: '2021-01-01 17:30:00'},
]

Two elements of the list overlap if Math.max(start_1, start_2) < Math.min(end_1, end_2) .如果Math.max(start_1, start_2) < Math.min(end_1, end_2) ,则列表的两个元素重叠。

I'm unsure of your counting requirement for the number of overlapping time segments, but this should get you on the right path.我不确定您对重叠时间段数量的计数要求,但这应该会让您走上正确的道路。

const list = [
  { start_date: '2021-01-01 10:00:00', end_date: '2021-01-01 11:00:00'},
  { start_date: '2021-01-01 08:00:00', end_date: '2021-01-01 11:00:00'},
  { start_date: '2021-01-01 12:00:00', end_date: '2021-01-01 14:00:00'},
  { start_date: '2021-01-01 12:30:00', end_date: '2021-01-01 14:30:00'},
  { start_date: '2021-01-01 14:00:00', end_date: '2021-01-01 17:30:00'},
];

// Step 1 : Convert to Date objects
const dt_list = list.map((currItem) => {
  return [new Date(currItem.start_date), new Date(currItem.end_date)];
});

// Map over arrays of Date values
const result = dt_list.map((item, index) => {
  let count = 0;
  // Count overlaps with remainder of list
  for (let i=(index + 1); i < dt_list.length; i++) {
    if (Math.max(item[0], dt_list[i][0]) < Math.min(item[1], dt_list[i][1]))
      count += 1;
  }
  return count;
}).reduce((sum, current) => {
  return sum + current;
}, 0);

console.log(result); // 3

Assuming your date format is always YYYY-MM-DD hh:mm:ss , you can use string comparisons for comparing the date/times.假设您的日期格式始终YYYY-MM-DD hh:mm:ss ,您可以使用字符串比较来比较日期/时间。 If other formats are possible as well, I would suggest using some library like Moment.js .如果其他格式也是可能的,我建议使用像Moment.js这样的

You could loop over the ranges and check for each range whether it overlaps another one, like:您可以遍历范围并检查每个范围是否与另一个范围重叠,例如:

 const ranges = [ { start_date: '2021-01-01 10:00:00', end_date: '2021-01-01 11:00:00'}, { start_date: '2021-01-01 08:00:00', end_date: '2021-01-01 11:00:00'}, { start_date: '2021-01-01 12:00:00', end_date: '2021-01-01 14:00:00'}, { start_date: '2021-01-01 12:30:00', end_date: '2021-01-01 14:30:00'}, { start_date: '2021-01-01 14:00:00', end_date: '2021-01-01 17:30:00'}, ]; let overlaps = 0; for (let i = 0; i < ranges.length; i++) { const range1 = ranges[i]; for (let j = i + 1; j < ranges.length; j++) { const range2 = ranges[j]; if (!(range1.start_date >= range2.end_date || range2.end_date <= range1.start_date || range2.start_date >= range1.end_date || range1.end_date <= range2.start_date)) { console.log(JSON.stringify(ranges[i]) + ' overlaps ' + JSON.stringify(ranges[j])); overlaps++; } } } console.log('Overlaps: ' + overlaps); // Overlaps: 3

You could convert all the dates to timeStamps ( seconds since 1970/01/01 ) for better comparison.您可以将所有日期转换为时间戳(自 1970/01/01 以来的秒数)以进行更好的比较。 Then push all of them into a new array converted_dates[] to use them inside a double loop where a conditional statement its implemented to see if there is an overlap between any of the ranges.然后将它们全部推入一个新数组converted_dates[]以在双循环中使用它们,其中执行条件语句以查看任何范围之间是否存在重叠。

This code should work with any date and any time, keeping in mind, that to do so, it should maintain the date format of the original range array.此代码应该适用于任何日期和任何时间,请记住,要这样做,它应该保持原始范围数组的日期格式。

Try the following snippet试试下面的片段

 const ranges = [ { start_date: '2021-01-01 10:00:00', end_date: '2021-01-01 11:00:00'}, { start_date: '2021-01-01 08:00:00', end_date: '2021-01-01 11:00:00'}, { start_date: '2021-01-01 12:00:00', end_date: '2021-01-01 14:00:00'}, { start_date: '2021-01-01 12:30:00', end_date: '2021-01-01 14:30:00'}, { start_date: '2021-01-01 14:00:00', end_date: '2021-01-01 17:30:00'}, ]; const converted_dates = []; for(let range of ranges){ var start_sliced_date = range.start_date.slice(0,10); var start_sliced_hour = range.start_date.slice(11,19); var end_sliced_date = range.end_date.slice(0,10); var end_sliced_hour = range.end_date.slice(11,19); // Create a date object to use getTime() method let newDate = new Date(start_sliced_date + "T" + start_sliced_hour); let start_timeStamp = newDate.getTime()/1000; newDate = new Date(end_sliced_date + "T" + end_sliced_hour); let end_timeStamp = newDate.getTime()/1000; // Create a new array with the dates converted to timeStamps converted_dates.push({ "start": start_timeStamp, "end": end_timeStamp }); } var count = 0; for(var i = 0; i < converted_dates.length; i++){ let end = converted_dates[i].end; for(var pos = i + 1; pos < converted_dates.length; pos++){ let otherStart = converted_dates[pos].start; // Is there an overlap? if(end>otherStart){ count++, console.log('Overlap of range ' + (i + 1) + ' with ' + (pos + 1)); } } } console.log('Total number of overalped ranges: ' + count);

If you want to find the max number of overlaps:如果要查找最大重叠数:

  1. You can insert all dates to one big dict or map (In our case size will be 10).您可以将所有日期插入一个大字典或 map(在我们的案例中大小为 10)。 Key represents the the date itself (no matter if it's start or end) and value is either 's' for start_date or 'e' for end_date.键表示日期本身(无论是开始日期还是结束日期),值是 start_date 的“s”或 end_date 的“e”。
  2. Sort the array in increasing order by date.按日期升序对数组进行排序。
  3. Hold a var named count.持有一个名为 count 的 var。 While linear looping through the dict, increase the count by 1 when you meet a starting point and decrease by 1 when you meet a ending point.在字典中线性循环时,当您遇到起点时将计数增加 1,当您遇到终点时减少 1。 (Key doesn't matter in this case, just value) (在这种情况下,键无关紧要,只是值)

Notice.注意。 you have to keep in mind the maximum point count had reached.您必须记住已达到的最大点数。 There's your max overlaps!有你的最大重叠!

Time complexity O(N log(N)).时间复杂度 O(N log(N))。 Space complexity O(N).空间复杂度 O(N)。

I hope this answer was helpful.我希望这个答案有帮助。

Thank you!谢谢!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM