用于折叠一组可能重叠的范围的好的通用算法是什么?
我有一个方法可以获取此类的多个对象。
class Range<T>
{
public T Start;
public T End;
}
在我的例子中,T
是DateTime
,但为了简单起见,让我们使用int
。 我想要一种方法,将这些范围折叠成覆盖相同“区域”但不重叠的范围。
因此,如果我有以下范围
- 1 到 5
- 3 到 9
- 11 到 15
- 12 到 14
- 13 到 20
该方法应该给我
- 1 到 9
- 11 到 20
猜猜它会被称为联合? 我想方法签名可能看起来像这样:
public static IEnumerable<Range<T>> Collapse<T>(
this IEnumerable<Range<T>>,
IComparable<T> comparer)
{
...
}
我在这里查看了一些类似的其他问题,但我还没有找到它的实现。 这个答案 和同一问题的其他一些答案描述了算法,但我不太确定我是否理解这些算法。 也不是特别擅长实现算法,所以我希望这里有人可以帮助我。
I have a method that gets a number of objects of this class
class Range<T>
{
public T Start;
public T End;
}
In my case T
is DateTime
, but lets use int
for simplicity. I would like a method that collapses those ranges into ones that cover the same "area" but that do not overlap.
So if I had the following ranges
- 1 to 5
- 3 to 9
- 11 to 15
- 12 to 14
- 13 to 20
The method should give me
- 1 to 9
- 11 to 20
Guess it would be called a union? I imagine the method signature could look something like this:
public static IEnumerable<Range<T>> Collapse<T>(
this IEnumerable<Range<T>>,
IComparable<T> comparer)
{
...
}
I have looked at some other questions here that are kind of similar, but I haven't found an implementation of this yet. This answer and some other answers to the same question describes algorithms, but I am not quite sure if I understand the algorithms. Not especially good at implementing algorithms either, so I was hoping someone here could help me out.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
这似乎有效并且很容易理解。
这是我在评论中提到的变化。 它基本上是相同的事情,但是对结果进行了一些检查和生成,而不是在返回之前收集在列表中。
This seems to works and is easy to understand.
Here is the variation which I mentioned in the comments. It's basically the same thing, but with some checking and yielding of the results instead of collecting in a list before returning.
适合非冗长爱好者的 Python 解决方案:
A Python solution for the non-verbosephile:
像这样的东西。 没有验证它是否适用于所有输入。
Something like this. Didn't verify that it works with all inputs.
红宝石版本。 在合并之前对范围进行排序似乎是一个好主意。
A ruby version. Sort the ranges before merge seems to be a good idea.
折叠列表的想法对我来说简直就是“减少”。 但它最终并没有像我希望的那样优雅。
感谢 yairchu 输入数据,以便我可以剪切和粘贴它:)
The idea of collapsing a list just screamed out "reduce" to me. It didn't end up quite as elegant as I had hoped though.
thanks to yairchu for typing in the data so I could cut and paste it :)
这可能可以优化...
This could probably be optimized...
这是一个简单的循环实现,但至少是清楚的。
-- 这行故意没有意义,是为了解决 markdown 问题 --
Here is a simple looping impelmentation, but at least is clear.
-- this line intentionally meaningless, to fix markdown problem --
将另一顶帽子扔进擂台。 与 Gary W 的实现非常相似(我从中得到了排序列表方法),但作为测试用例完成,并在 Range 类中添加了一些有用的函数。
Tossing another hat into the ring. Very much the same implementation as Gary W's (from which I got the sorted list approach), but done as a test case and with some helpful functions added to the Range class.
这是一个轻微的变化。 我不需要折叠无序列表,我想维护一个已排序的列表。 在我的例子中,这更有效。 我将其发布在这里,以防它对阅读该帖子的其他人有用。 显然可以很容易地变得通用。
This is a slight variation. I didn't need to collapse an unordered list, I wanted to maintain a sorted list instead. This is more efficient in my case. I am posting it here in case it is useful to anyone else reading this thread. Obviously can be made generic very easily.
基于Python答案的Go算法:
Algorithm in Go based on the Python answer: