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 使用LINQ混合2个阵列_.net_Linq - Fatal编程技术网

.net 使用LINQ混合2个阵列

.net 使用LINQ混合2个阵列,.net,linq,.net,Linq,我需要将两个数组(List)相交,只保留不同的元素,并将一个数组的元素与另一个数组的元素混合,如下所示: A1 B1 C1 D1 W2 X2 Y2 Z2 => A1 W2 B1 X2 C1 Y2 D1 Z2 A1 B1 A1 D1 W2 X2 Y2 Z2 => A1 W2 B1 X2 Y2 D1 Z2 // repeating A1 A1 B1 A1 D1 Z2 X2 Y2 Z2 => A1 Z2 B1 X2

我需要将两个数组(
List
)相交,只保留不同的元素,并将一个数组的元素与另一个数组的元素混合,如下所示:

    A1 B1 C1 D1
    W2 X2 Y2 Z2 
 => A1 W2 B1 X2 C1 Y2 D1 Z2


    A1 B1 A1 D1
    W2 X2 Y2 Z2 
 => A1 W2 B1 X2 Y2 D1 Z2 // repeating A1


    A1 B1 A1 D1
    Z2 X2 Y2 Z2 
 => A1 Z2 B1 X2 Y2 D1  // repeating A1, Z2

    A1 B1 C1 D1 E1
    Z2 X2 Y2 
 => A1 Z2 B1 X2 C1 Y2 D1 E1
最佳的LINQ查询是什么

(顺便说一句,
List
不是数组。)

如果您使用.NET 4,并且假设数组长度相同,我认为这将满足您的需要:

var query = first.Zip(second, (x, y) => new[] { x, y })
                 .SelectMany(pair => pair)
                 .Distinct();
编辑:正如评论中指出的那样,
Distinct
的顺序不受保证。然而,我希望它实际上在实践中保持不变。。。考虑到我所建议的其他变化,这些变化只会以积极(微小)的方式影响可观察的结果,我无法想象这会发生变化

Lassespeholt的解决方案处理交织部分。如果您想要绝对有保证的订购,您可以始终自己实施Disrinct,就像我在Edulink中所做的那样:

public static IEnumerable<TSource> OrderPreservingDistinct<TSource>(
    this IEnumerable<TSource> source)
{
    return source.OrderPreservingDistinct(EqualityComparer<TSource>.Default);
}

public static IEnumerable<TSource> OrderPreservingDistinct<TSource>(
    this IEnumerable<TSource> source,
    IEqualityComparer<TSource> comparer)
{
    if (source == null)
    {
        throw new ArgumentNullException("source");
    }
    return OrderPreservingDistinct(source, comparer ?? 
                                           EqualityComparer<TSource>.Default);
}

private static IEnumerable<TSource> OrderPreservingDistinct<TSource>(
    IEnumerable<TSource> source,
    IEqualityComparer<TSource> comparer)
{
    HashSet<TSource> seenElements = new HashSet<TSource>(comparer);
    foreach (TSource item in source)
    {
        if (seenElements.Add(item))
        {
            yield return item;
        }
    }
}

也许不只是使用LINQ,但我认为使用简单且足够快

//List<string> l1 = new List<string>() { "A1", "B1", "C1", "D1" };
List<string> l1 = new List<string>() { "A1", "B1", "A1", "D1" };
//List<string> l2 = new List<string>() { "W2", "X2", "Y2", "Z2" };
List<string> l2 = new List<string>() { "Z2", "X2", "Y2", "Z2" };
List<string> ls = new List<string>();
ls.AddRange(l1);
ls.AddRange(l2);
ls = ls.Distinct().ToList();
//列表l1=新列表(){“A1”、“B1”、“C1”、“D1”};
列表l1=新列表(){“A1”、“B1”、“A1”、“D1”};
//列表l2=新列表(){“W2”、“X2”、“Y2”、“Z2”};
列表l2=新列表(){“Z2”、“X2”、“Y2”、“Z2”};
列表ls=新列表();
ls.AddRange(l1);
ls.AddRange(l2);
ls=ls.Distinct().ToList();

一种交织扩展方法(取代Jon Skeets版本中的
Zip
/
SelectMany
)。这可能会快一点,如果列表的长度不相等,它会包括最长列表的剩余部分:

public static IEnumerable<T> Interleave<T>(this IEnumerable<T> first, IEnumerable<T> second)
{
    var e0 = first.GetEnumerator();
    var e1 = second.GetEnumerator();

    bool e0HasValue = false;
    bool e1HasValue = false;

    // Could be made a little faster by not checking both when one is empty
    while ((e0HasValue = e0.MoveNext()) | (e1HasValue = e1.MoveNext()))
    {
        if (e0HasValue)
            yield return e0.Current;

        if (e1HasValue)
            yield return e1.Current;
    }
}

当然,这个答案并不能解决Jon Skeet答案评论中描述的关于
Distinct
的不确定性。但它可以与Jon Skeet的保序扩展方法相结合。

这看起来不像是正常意义上的交叉点…@Jon Skeet:Edit to'Mix'+添加了不同的数组大小。重申一下,
列表
不是数组。我想你是想引用序列的一般概念。@Jon:如果你想的话,就让它成为序列吧。我不认为这对这个话题真的很重要。在我看来,表达的清晰总是非常重要的。了解不同术语的含义并恰当地使用它们是非常值得的。嗯。。。如果我们抑制约束“数组的长度相同”,它会改变一些东西?比如说,如果长度不同,我总是可以用最后一个元素的长度来完成最小的数组…可能值得指出的是,Distinct()之后的顺序是显式未指定的()[解释:)]@塞尔希奥:这变得更加棘手,因为当较短的列表完成时,Zip将停止。@塞尔希奥:不,绝对不是-你应该使用LasseSpeholt的答案,正如我的答案中指定的那样。我认为把它复制到我的答案中没有任何意义。
public static IEnumerable<T> Interleave<T>(this IEnumerable<T> first, IEnumerable<T> second)
{
    var e0 = first.GetEnumerator();
    var e1 = second.GetEnumerator();

    bool e0HasValue = false;
    bool e1HasValue = false;

    // Could be made a little faster by not checking both when one is empty
    while ((e0HasValue = e0.MoveNext()) | (e1HasValue = e1.MoveNext()))
    {
        if (e0HasValue)
            yield return e0.Current;

        if (e1HasValue)
            yield return e1.Current;
    }
}
var result = firstList.Interleave(secondList).Distinct();