鉴于相同类型的Ñ可枚举该升序顺序返回不同的元件,例如N路相交:排序可枚举
IEnumerable<char> sx = Intersect(new[] { s1, s2, s3 });
Debug.Assert(sx.SequenceEqual("djs"));
“高效” 在这里是指
- 输入枚举应该只被枚举一次,
- 输入枚举元素应该只在需要时才能被检索,而
- 该算法不应该递归枚举自己的输出。
我需要一些提示如何解决问题。
这是我的(幼稚)尝试到目前为止:
static IEnumerable<T> Intersect<T>(IEnumerable<T>[] enums)
{
return enums[0].Intersect(
enums.Length == 2 ? enums[1] : Intersect(enums.Skip(1).ToArray()));
}
Enumerable.Intersect收集第一枚举成一个HashSet,然后枚举第二枚举并产生所有匹配元素。 Intersect
然后递归地将结果与下一个可枚举值相交。 这显然不是很有效率(它不符合约束条件)。而且它并没有利用这些元素完全排序的事实。
这是我试图交叉两个枚举。也许它可以推广为n enumerables?
static IEnumerable<T> Intersect<T>(IEnumerable<T> first, IEnumerable<T> second)
{
using (var left = first.GetEnumerator())
using (var right = second.GetEnumerator())
{
var leftHasNext = left.MoveNext();
var rightHasNext = right.MoveNext();
var comparer = Comparer<T>.Default;
while (leftHasNext && rightHasNext)
{
switch (Math.Sign(comparer.Compare(left.Current, right.Current)))
{
case -1:
leftHasNext = left.MoveNext();
break;
case 0:
yield return left.Current;
leftHasNext = left.MoveNext();
rightHasNext = right.MoveNext();
break;
case 1:
rightHasNext = right.MoveNext();
break;
}
}
}
}
重新评论;为什么你需要把它与其他任何东西结合起来?它似乎是“按原样”完成这项工作的? – 2009-12-14 07:07:28
回复评论 – 2009-12-14 12:51:30
重新“聚合”(评论) - 不完全;如果你使用'Empty()'作为种子,你的答案总是*为空......但除初始条件外 - 非常多! – 2009-12-15 05:22:48