.net 给定IComparer,Zip两个有序IEnumerable-s,只配对相等的元素?
我需要迭代两个有序的.net 给定IComparer,Zip两个有序IEnumerable-s,只配对相等的元素?,.net,linq,.net,Linq,我需要迭代两个有序的IEnumerable-s,a和b,由给定的IComparer,“并排”和Zip相等的元素排序(根据相同的IComparer相等) 我需要Zip将其他集合中不匹配的所有元素与null(或default值,无论什么)进行压缩 通过Zipping,我的意思是“返回f()调用结果的集合,其中f()是一个给定的闭包,包含两个参数,一个来自a,另一个来自b” a和b可以有不同数量的元素,并且不必匹配1:1 例如: IComparer comparer = ...; int[] a =
IEnumerable
-s,a
和b
,由给定的IComparer
,“并排”和Zip
相等的元素排序(根据相同的IComparer
相等)
我需要Zip
将其他集合中不匹配的所有元素与null
(或default
值,无论什么)进行压缩
通过Zip
ping,我的意思是“返回f()
调用结果的集合,其中f()
是一个给定的闭包,包含两个参数,一个来自a
,另一个来自b
”
a
和b
可以有不同数量的元素,并且不必匹配1:1
例如:
IComparer comparer = ...;
int[] a = { 1, 2, 4, 7, 7 };
int[] b = { -1, 1, 3, 4, 7, 8 };
var zipped = EvenMoreLinq.ZipEqual(a, b, comparer, (a, b) => new int[]{ a, b });
我希望压缩的是:
{ {0, -1}, {1, 1}, {2, 0}, {0, 3}, {4, 4}, {7, 7}, {7, 0}, {0, 8} };
a
和b
中的相等元素应与其他集合中的匹配元素一样匹配
输出集合需要保持源顺序
是否存在这样的库实现?假设Jon的评论回答为“是”,则实现可能如下所示:
public static IEnumerable<TResult> ZipEqual<TFirst, TSecond, TResult>(
this IEnumerable<TFirst> first, IEnumerable<TSecond> second,
Func<TFirst, TSecond, TResult> resultSelector,
IComparer comparer)
{
var enumerator1 = first.GetEnumerator();
var enumerator2 = second.GetEnumerator();
var enumerator1HasElement = enumerator1.MoveNext();
var enumerator2HasElement = enumerator2.MoveNext();
while(enumerator1HasElement || enumerator2HasElement)
{
if(!enumerator2HasElement)
{
yield return resultSelector(enumerator1.Current, default(TSecond));
enumerator1HasElement = enumerator1.MoveNext();
}
else if(!enumerator1HasElement)
{
yield return resultSelector(default(TFirst), enumerator2.Current);
enumerator2HasElement = enumerator2.MoveNext();
}
else
{
var compareResult = comparer.Compare(enumerator1.Current,
enumerator2.Current);
if(compareResult == 0)
{
yield return resultSelector(enumerator1.Current,
enumerator2.Current);
enumerator1HasElement = enumerator1.MoveNext();
enumerator2HasElement = enumerator2.MoveNext();
}
else if(compareResult < 0)
{
yield return resultSelector(enumerator1.Current,
default(TSecond));
enumerator1HasElement = enumerator1.MoveNext();
}
else
{
yield return resultSelector(default(TFirst),
enumerator2.Current);
enumerator2HasElement = enumerator2.MoveNext();
}
}
}
}
公共静态IEnumerable ZipEqual(
这个IEnumerable第一,IEnumerable第二,
Func结果选择器,
IComparer(比较器)
{
var enumerator1=first.GetEnumerator();
var enumerator2=second.GetEnumerator();
变量enumerator1HasElement=enumerator1.MoveNext();
变量enumerator2HasElement=enumerator2.MoveNext();
while(枚举器1HasElement | |枚举器2HasElement)
{
如果(!enumerator2HasElement)
{
产生返回结果选择器(enumerator1.Current,默认值(TSecond));
enumerator1HasElement=enumerator1.MoveNext();
}
如果(!enumerator1HasElement)
{
产生返回结果选择器(默认值(TFirst),枚举数2.Current);
enumerator2HasElement=enumerator2.MoveNext();
}
其他的
{
var compareResult=比较器.Compare(枚举器1.Current,
枚举器2(当前);
if(compareResult==0)
{
产生返回结果选择器(枚举器1.Current,
枚举器2(当前);
enumerator1HasElement=enumerator1.MoveNext();
enumerator2HasElement=enumerator2.MoveNext();
}
else if(比较结果<0)
{
产生返回结果选择器(枚举器1.Current,
违约(TSecond));
enumerator1HasElement=enumerator1.MoveNext();
}
其他的
{
收益率返回结果选择器(默认值(TFirst),
枚举器2(当前);
enumerator2HasElement=enumerator2.MoveNext();
}
}
}
}
假设对Jon评论的回答是“是”,则实现可能如下所示:
public static IEnumerable<TResult> ZipEqual<TFirst, TSecond, TResult>(
this IEnumerable<TFirst> first, IEnumerable<TSecond> second,
Func<TFirst, TSecond, TResult> resultSelector,
IComparer comparer)
{
var enumerator1 = first.GetEnumerator();
var enumerator2 = second.GetEnumerator();
var enumerator1HasElement = enumerator1.MoveNext();
var enumerator2HasElement = enumerator2.MoveNext();
while(enumerator1HasElement || enumerator2HasElement)
{
if(!enumerator2HasElement)
{
yield return resultSelector(enumerator1.Current, default(TSecond));
enumerator1HasElement = enumerator1.MoveNext();
}
else if(!enumerator1HasElement)
{
yield return resultSelector(default(TFirst), enumerator2.Current);
enumerator2HasElement = enumerator2.MoveNext();
}
else
{
var compareResult = comparer.Compare(enumerator1.Current,
enumerator2.Current);
if(compareResult == 0)
{
yield return resultSelector(enumerator1.Current,
enumerator2.Current);
enumerator1HasElement = enumerator1.MoveNext();
enumerator2HasElement = enumerator2.MoveNext();
}
else if(compareResult < 0)
{
yield return resultSelector(enumerator1.Current,
default(TSecond));
enumerator1HasElement = enumerator1.MoveNext();
}
else
{
yield return resultSelector(default(TFirst),
enumerator2.Current);
enumerator2HasElement = enumerator2.MoveNext();
}
}
}
}
公共静态IEnumerable ZipEqual(
这个IEnumerable第一,IEnumerable第二,
Func结果选择器,
IComparer(比较器)
{
var enumerator1=first.GetEnumerator();
var enumerator2=second.GetEnumerator();
变量enumerator1HasElement=enumerator1.MoveNext();
变量enumerator2HasElement=enumerator2.MoveNext();
while(枚举器1HasElement | |枚举器2HasElement)
{
如果(!enumerator2HasElement)
{
产生返回结果选择器(enumerator1.Current,默认值(TSecond));
enumerator1HasElement=enumerator1.MoveNext();
}
如果(!enumerator1HasElement)
{
产生返回结果选择器(默认值(TFirst),枚举数2.Current);
enumerator2HasElement=enumerator2.MoveNext();
}
其他的
{
var compareResult=比较器.Compare(枚举器1.Current,
枚举器2(当前);
if(compareResult==0)
{
产生返回结果选择器(枚举器1.Current,
枚举器2(当前);
enumerator1HasElement=enumerator1.MoveNext();
enumerator2HasElement=enumerator2.MoveNext();
}
else if(比较结果<0)
{
产生返回结果选择器(枚举器1.Current,
违约(TSecond));
enumerator1HasElement=enumerator1.MoveNext();
}
其他的
{
收益率返回结果选择器(默认值(TFirst),
枚举器2(当前);
enumerator2HasElement=enumerator2.MoveNext();
}
}
}
}
编辑
分组是可以避免的,但结果明显类似于
公共静态IEnumerable ZipEqual(
这是一个数不清的来源,
我是数不清的其他人,
IComparer比较器=空)
{
如果(其他==null)
{
抛出新的异常(“其他”);
}
if(比较器==null)
{
comparer=comparer.Default;
}
var first=source.OrderBy(t=>t,comparer.GetEnumerator();
var second=other.OrderBy(t=>t,comparer.GetEnumerator();
var firstMore=first.MoveNext();
var secondMore=second.MoveNext();
while(firstMore&&secondMore)
{
var comp=比较器比较(第一个电流,第二个电流);
如果(comp==0)
{
产生返回元组.Create(first.Current,second.Current);
firstMore=first.MoveNext();
secondMore=second.MoveNext();
继续;
}
如果(补偿>0)
{
返回Tuple.Create(默认值(T),second.Current);
秒=秒
public static IEnumerable<Tuple<T, T>> ZipEqual<T>(
this IEnumerable<T> source,
IEnumerable<T> other,
IComparer<T> comparer = null)
{
if (other == null)
{
throw new ArgumentNullException("other");
}
if (comparer == null)
{
comparer = Comparer<T>.Default;
}
var orderedGroups =
source.Select(t => new { Value = t, First = true })
.Concat(other.Select(t => new { Value = t, First = false }))
.ToLookup(a => a.Value)
.OrderBy(l => l.Key, comparer);
foreach (var group in orderedGroups)
{
var firsts = group.Where(a => a.First).Select(a => a.Value).ToList();
var seconds = group.Where(a => !a.First).Select(a => a.Value).ToList();
var limit = Math.Max(firsts.Count, seconds.Count);
for (var i = 0; i < limit; i++)
{
yield return Tuple.Create(
firsts.ElementAtOrDefault(i),
seconds.ElementAtorDefault(i));
}
}
}