Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 给定IComparer,Zip两个有序IEnumerable-s,只配对相等的元素?_.net_Linq - Fatal编程技术网

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