5

我有一份工作项目清单。每个工作项都有一个开始和结束时间。

所以,基本上它看起来像这样:

List<Work> works = new List<Work>();
works.Add(new Work(
  new DateTime(2013, 4, 30, 9, 0, 0),
  new DateTime(2013, 4, 30, 11, 0, 0));

现在我想得到工作的总时间。同样,基本上这很容易:

09:00-11:00 => 2 hours
13:00-17:00 => 4 hours
----
06:00 hours

这只是总和。

但是现在变得困难了:如果我想提取并行时间,我该如何计算这个总和?

例如,

09:00-11:00 => 2 hours
10:00-11:30 => 1.5 hours
13:00-17:00 => 4 hours
----
06:30 hours

是 6.5 小时,但总和是 7.5 小时。两个工作项映射到 10 点到 11 点之间的时间这一事实有所不同。

对于可以以基本上所有可能的方式(周围、开始重叠、结束重叠,包括)相互重叠的任意数量的工作项,我该如何解决这个问题?

4

2 回答 2

6

创建 (time, value) 对,其中 value 为 +1 表示工作开始,-1 表示结束。然后按日期对对进行排序。迭代你得到的列表,你可以计算值的总和——当它是正数时,工作正在“继续”。迭代时,标记值总和从 0 变为正数和从正数变为 0 的时刻。您将得到不相交的区间。

例子:

11 - 13, 12 - 16, 15 - 17, 18 - 19

给你 (11, 1) (12, 1) (13 -1) (15, 1) (16, -1) (17, -1) (18, 1) (19, -1)

总和为 (11, 1) (12, 2) (13 1) (15, 2) (16, 1) (17, 0) (18, 1) (19, 0),

所以不相交的周期是 (11, 17) 和 (18, 19)

于 2013-04-30T09:15:02.610 回答
2

嗯,我曾经解决过类似的问题(不是时间,而是范围重叠)。我应用的解决方案非常简单:

  1. 按升序对元素进行排序
  2. 从第一个元素开始,看它是否与下一个元素重叠
  3. 如果是 - 重新处理元素,提取重叠部分作为新元素,修改旧元素以在重叠期之前/之后结束
  4. 在两个旧元素之间插入新创建的元素
  5. 继续处理

它应该可以正常工作,但是如果您有大量数据,可能会有更好的方法来解决它。这只是最简单的方法(至少对我而言)。您最终将获得没有重叠部分的时间列表,因此您将能够迭代列表并总结时间。

于 2013-04-30T09:18:35.407 回答