将更改列表压缩为较小的列表
Posted
技术标签:
【中文标题】将更改列表压缩为较小的列表【英文标题】:Condensing list of changes to a smaller list 【发布时间】:2022-01-10 01:10:24 【问题描述】:我目前正在寻找一种可以帮助我压缩更改列表的算法。
更改类如下所示
public class change
DateTime From;
DateTime To;
string[] ChangedProperties;
然后将其实例收集在这样的列表中
string[] changes1 = "A", "B", "C";
string[] changes2 = "D";
string[] changes3 = "A","B","C","E";
string[] changes4 = "A";
string[] changes5 = "B";
string[] changes6 = "B";
Change first = new Change()
From = new DateTime(2008, 1, 1, 0, 00, 00),
To = new DateTime(2080, 1, 1, 0, 00, 00),
Active = changes1
;
Change second = new Change()
From = new DateTime(2008, 1, 1, 0, 00, 00),
To = new DateTime(2010, 1, 1, 0, 00, 00),
Active = changes2
;
Change third = new Change()
From = new DateTime(2008, 1, 1, 0, 00, 00),
To = new DateTime(2020, 1, 1, 0, 00, 00),
Active = changes3
;
Change fourth = new Change()
From = new DateTime(2005, 1, 1, 0, 00, 00),
To = new DateTime(2008, 1, 1, 0, 00, 00),
Active = changes4
;
Change fifth = new Change()
From = new DateTime(2003, 1, 1, 0, 00, 00),
To = new DateTime(2008, 1, 1, 0, 00, 00),
Active = changes5
;
Change sixth = new Change()
From = new DateTime(2008, 1, 1, 0, 00, 00),
To = new DateTime(2015, 1, 1, 0, 00, 00),
Active = changes6
;
List<Change> changes = new List<Change>();
changes.Add(first);
changes.Add(second);
changes.Add(third);
changes.Add(fourth);
changes.Add(fifth);
changes.Add(sixth);
我想压缩这个列表,使反映的变化在时间上完全重叠。
例如
first
在日期时间跨度 2008-1-1T00:00:00 到 2080-1-1T00:00:00 中更改属性 "A", "B", "C"
但 sixth
在日期时间跨度 2008-1-1T00 中更改属性 B :00:00 至 2015-1-1T00:00:00。第六次变更提供的信息是多余的,因为它完全包含在第一次变更中
first : |---------|
Sixth : |------|
精简列表应该只包含
变化:第一,第二,(仅从第三改变E),第五
这是我目前所拥有的:
https://dotnetfiddle.net/9ytlh7
【问题讨论】:
按开始时间然后结束时间排序,从左到右扫,如果改变i+1
的开始时间>=改变i
s开始时间&&
改变i+1
s结束时间is 结束时间,查看这两个属性并根据需要合并。这构成了一个O(n log n)
算法。
@user1984 你能用一些伪代码形式化它吗?为什么不这样订购? foreach(var change in changes.OrderByDescending(x => x.To - x.From).ThenByDescending(x => x.Active.Length))
我假设大多数都能够适应最大的,并且需要较少的评估?
@user1984 用户方法不起作用,它会在末尾创建一个额外的 B,由第一个 01/01/2003 00:00:00 01/01/2008 00:00 覆盖: 00 B 01/01/2005 00:00:00 01/01/2008 00:00:00 A 01/01/2008 00:00:00 01/01/2010 00:00:00 D 01/01/2008 00 :00:00 01/01/2015 00:00:00 B
您可以为此使用分段树:en.wikipedia.org/wiki/Segment_tree
【参考方案1】:
这就是我最终这样做的方式......
https://dotnetfiddle.net/OliMgt
不确定这是否有效?
【讨论】:
以上是关于将更改列表压缩为较小的列表的主要内容,如果未能解决你的问题,请参考以下文章