【问题标题】:Algorithm to merge tagged intervals合并标记间隔的算法
【发布时间】:2019-09-24 16:20:34
【问题描述】:

我有一组Items,每个都有StartEnd

class Item
{
   int Value { get; }
   DateTimeOffset Start { get; }
   DateTimeOffset End { get; }
}

例如:

  • 1:2019/01/01 => 2019/12/31
  • 2:2020/01/01 => 2020/12/31

所以有 2 个不重叠的间隔。值1涵盖2019年全年,值2涵盖2020年全年。

但突然间,我意识到我忘记了一个中间值。

  • 3:2019/06/01 => 2019/08/01

所以我想用我忘记的值做某种“导入”操作。

它的结果应该是:

  • 1:2019/01/31 => 2019/05/31
  • 3:2019/06/01 => 2019/08/01
  • 1:2019/08/02 => 2019/12/31
  • 2:2020/01/01 => 2020/12/31

如您所见,值 3 已插入并与现有值协调。它应该被“合并”并修改现有的间隔,因此它们都不重叠。

我不知道如何执行生成结果项的“导入”。

【问题讨论】:

  • 你走了多远?您能否展示您尝试解决此问题的代码,或者告诉我们您遇到问题的地方?
  • 如何确定使用哪个值的优先级?比如说,如果你有 {1, 2020-01-01, 2020-01-31} 和 {2, 2020-01-01, 2020-01-31},应该使用哪个值?
  • 计算所有区间的并集(这通常会导致区间的不相交并集)并用输入的端点集对其进行划分。
  • @Xtros 导入的值优先于现有值。
  • @conditionalMethod 你能用一个例子来说明这个算法吗?我还是不明白你:(

标签: c# .net algorithm


【解决方案1】:

创建一个扩展方法。我假设该列表按开始日期排序。

public class Item
{
    public int Value { get; set; }
    public DateTimeOffset Start { get; set; }
    public DateTimeOffset End { get; set; }
}

public static class EnumerableExtensions
{
    public static IEnumerable<Item> WithUpdate(this IEnumerable<Item> enumerable)
    {
        using (var enumerator = enumerable.GetEnumerator())
        {
            enumerator.MoveNext();
            Item previous, current=null;
            previous = (Item)enumerator.Current;
            while (enumerator.MoveNext())
            {
                current = (Item)enumerator.Current;
                if (previous.End >= current.Start)
                {
                    previous.End = ((Item)enumerator.Current).Start.AddDays(-1);
                }
                yield return previous;
                previous = (Item)enumerator.Current;
            }
            yield return current;
        }
    }
}

static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");
        List<Item> list = new List<Item>() {
            new Item() { Value = 1, Start = DateTime.Now, End = DateTime.Now.AddDays(10) },
            new Item() { Value = 2, Start = DateTime.Now.AddDays(8), End = DateTime.Now.AddDays(15) },
            new Item() { Value = 3, Start = DateTime.Now.AddDays(12), End = DateTime.Now.AddDays(20) }
        };

        foreach (Item item in list) {
            Console.WriteLine("Star ={0},End={1}", item.Start.ToString(), item.End.ToString());
        }

        foreach (Item item in list.WithUpdate())
        {
            Console.WriteLine("Star ={0},End={1}", item.Start.ToString(), item.End.ToString());
        }
        Console.ReadLine();
        //Item item = new Item() { Value = 1, Start = DateTime.Now, End = DateTime.Now.AddDays(10) };
    }

【讨论】:

  • 你能检查一下代码吗?我试过了,还是不行:(
  • 请检查一下 我已附上调用程序
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多