繁体   English   中英

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

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

如果我有以下具有开始日期和结束日期的对象数组,我怎样才能最好地计算相互重叠的最大范围数? 我只想要最大数量的重叠范围的计数。 例如,我在最大重叠范围下方的示例是 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'},
]

如果Math.max(start_1, start_2) < Math.min(end_1, end_2) ,则列表的两个元素重叠。

我不确定您对重叠时间段数量的计数要求,但这应该会让您走上正确的道路。

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

假设您的日期格式始终YYYY-MM-DD hh:mm:ss ,您可以使用字符串比较来比较日期/时间。 如果其他格式也是可能的,我建议使用像Moment.js这样的

您可以遍历范围并检查每个范围是否与另一个范围重叠,例如:

 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

您可以将所有日期转换为时间戳(自 1970/01/01 以来的秒数)以进行更好的比较。 然后将它们全部推入一个新数组converted_dates[]以在双循环中使用它们,其中执行条件语句以查看任何范围之间是否存在重叠。

此代码应该适用于任何日期和任何时间,请记住,要这样做,它应该保持原始范围数组的日期格式。

试试下面的片段

 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);

如果要查找最大重叠数:

  1. 您可以将所有日期插入一个大字典或 map(在我们的案例中大小为 10)。 键表示日期本身(无论是开始日期还是结束日期),值是 start_date 的“s”或 end_date 的“e”。
  2. 按日期升序对数组进行排序。
  3. 持有一个名为 count 的 var。 在字典中线性循环时,当您遇到起点时将计数增加 1,当您遇到终点时减少 1。 (在这种情况下,键无关紧要,只是值)

注意。 您必须记住已达到的最大点数。 有你的最大重叠!

时间复杂度 O(N log(N))。 空间复杂度 O(N)。

我希望这个答案有帮助。

谢谢!

暂无
暂无

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

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