如何在c#中从两个列表中创建一个对象对列表

本文关键字:列表 两个 创建 一个对象 | 更新日期: 2023-09-27 18:06:15

我有两个对象列表。列表A和列表B。我需要创建列表C,它将列表A和列表B组合成一对。例如:

List A
object a1
object a2
object a3
List B
object b1
object b2
object b3
List C (creates pairs)
object c1 (object a1, object b1)
object c2 (object a2, object b2)
object c3 (object a3, object b3)

如何在c#中从两个列表中创建一个对象对列表

您可以使用System.Linq中的Enumerable.Zip()方法。

IEnumerable<Tuple<A, B>> pairs = listA.Zip(listB, (a, b) => Tuple.Create(a, b));

示例:

foreach (Tuple<A, B> pair in pairs)
{
    A a = pair.Item1;
    B b = pair.Item2;
}

遗憾的是,在。net中没有重载实现元组的自动化。这样的扩展看起来像这样:

public static IEnumerable<Tuple<TFirst, TSecond>> Zip<TFirst, TSecond>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second)
{
    return first.Zip(second, Tuple.Create);
}

这意味着你可以写这样的代码:

IEnumerable<Tuple<A, B>> pairs = listA.Zip(listB);

注意:另一种选择是创建匿名类型而不是Tuple,但这种方法的缺点是,由于类型没有名称,您将无法(有效地)将生成的IEnumerable传递出创建它的方法。

可以这样做:

public static IEnumerable<Tuple<T, U>> CombineWith<T, U>(this IEnumerable<T> first, IEnumerable<U> second)
{
    using (var firstEnumerator = first.GetEnumerator())
    using (var secondEnumerator = second.GetEnumerator())
    {
        bool hasFirst = true;
        bool hasSecond = true;
        while (
            // Only call MoveNext if it didn't fail last time.
            (hasFirst && (hasFirst = firstEnumerator.MoveNext()))
            | // WARNING: Do NOT change to ||.
            (hasSecond && (hasSecond = secondEnumerator.MoveNext()))
            )
        {
            yield return Tuple.Create(
                    hasFirst ? firstEnumerator.Current : default(T),
                    hasSecond ? secondEnumerator.Current : default(U)
                );
        }
    }
}
编辑:我非常喜欢Paul的回答。

像这样:

 var listA = new object[] { "1", "2", "3" };
 var listB = new object[] { "a", "b", "c" };
 var listC = Enumerable.Zip(listA,listB, (x,y)=>new {x,y});
 foreach (var item in listC)
 {
    Console.WriteLine("{0},{1}", item.x,item.y);
 }

输出:1,一个2, b3、c

。. NET Core 3为Zip方法增加了一个新的重载。它接受两个IEnumerables,并创建一个IEnumerable,其中包含两个IEnumerables中元素的值元组。

IEnumerable<(A a, B b)> pairs = listA.Zip(listB);

你可以用多种方式使用结果:

foreach((A a, B b) in pairs)
{
    // Do something with a and b
}
foreach(var (a, b) in pairs)
{
    // Do something with a and b
}
foreach(var pair in pairs)
{
    A a = pair.a;
    B b = pair.b;
}

我建议使用元组列表

http://msdn.microsoft.com/en-us/library/system.tuple.aspx。

使用System.Linq Enumerable.Zip方法(不指定函数参数Func)的潜在解决方案如下(注意,我使用int来提供一个简单的具体示例):

List<int> list1 = new List<int>() {1,2,3,4,5};
List<int> list2 = new List<int>() {5,4,3,2,1};
IEnumerable<(int, int)> pairs;
pairs = list1.Zip(list2);
Console.WriteLine(string.Join(", ", pairs));

输出:

(1, 5), (2, 4), (3, 3), (4, 2), (5, 1)