首页 > 解决方案 > 合并标记间隔的算法

问题描述

我有一套,Items每个都有StartEnd

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

例如:

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

但突然间,我意识到我忘记了一个介于两者之间的值。

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

它的结果应该是:

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

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

标签: c#.netalgorithm

解决方案


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

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

推荐阅读