首页 > 解决方案 > 是否可以仅使用 LINQ 将 2 个数组合并为具有 2 个字段的结构数组?

问题描述

我想知道理论上是否可以仅使用 LINQ 将两个 int 数组合并为一个结构数组,其中每个数组都进入其各自的字段?

因此,假设我们有 2 个称为numbers_rawand的 int 数组categories_raw,并且class Record有 2 个字段。

使用程序代码,它看起来像这样:

class Record {
    public int number;
    public int category;
}
int[] numbers_raw =    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 14, -4 };
int[] categories_raw = { 0, 0, 0, 0, 1, 1, 1, 1, 2,  2,  2 };
var records = new List<Record>();
for (int ii = 0; ii < numbers_raw.Length; ii++) {
    records.Add(new Record { number = numbers_raw[ii], category = categories_raw[ii] });
}

如果我们只有 1 个数组和 1 个字段,我们可以这样做:

var records = numbers_raw.Select(x => new Record { number = x });

但是我不确定如何以使用两个数组的方式进行操作,categories_raw进入category现场并numbers_raw进入number现场。

我不确定是否可以使用 LINQ。

标签: c#linq

解决方案


Enumerable.Zip是你需要的:

List<Record> records = numbers_raw
    .Zip(categories_raw, (n, c) => new Record { number = n, category = c})
    .ToList();

如果两个集合中的一个较大,Zip则取所有项目直到共同的最大计数。例如,如果一个序列有三个元素,而另一个序列有四个,则结果序列将只有三个元素。

这让我想知道是否有任何数量的数组的通用解决方案,但我认为没有。

你是对的,没有ZipAll,也不容易建立一个。如果你有 3 或 4 个你仍然可以使用Zip,只需将它们连接起来:

List<Record> records = numbers_raw
    .Zip(categories_raw, (first, second) => (first, second))
    .Zip(thirdSeq, (both, third) => new Record { number = both.first, category = both.second, thirdProperty = third})
    .ToList();

或提供扩展方法(这已经存在于 C#6 但仅适用于 3):

public static class EnumerableExtensions
{
    public static IEnumerable<TResult> Zip<TFirst, TSecond, TThird, TResult>(
        this IEnumerable<TFirst> first, 
        IEnumerable<TSecond> second, 
        IEnumerable<TThird> third, 
        Func<TFirst, TSecond, 
        TThird, TResult> resultSelector)
    {
        using (IEnumerator<TFirst> e1 = first.GetEnumerator())
        using (IEnumerator<TSecond> e2 = second.GetEnumerator())
        using (IEnumerator<TThird> e3 = third.GetEnumerator())
            while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext())
                yield return resultSelector(e1.Current, e2.Current, e3.Current);
    }
}

但是这些方法只适用于几个序列。


推荐阅读