如何压缩两个不同大小的列表以创建一个与原始列表中最长的列表相同的新列表?

How to Zip two Lists of different size to create a new list that is same as the size of the longest amongst the original lists?

我有两个不同大小的 C# 列表,例如

List<int> list1 = new List<int>{1,2,3,4,5,6,7};
List<int> list2 = new List<int>{4,5,6,7,8,9};

我想使用 linq Zip 方法将这两个组合成一个大小为 list1 的元组列表。这是我正在寻找的结果列表

{(1,4), (2,5), (3,6), (4,7), (5,8), (6,9), (7,0)}  //this is of type List<(int,int)

由于 list1 的最后一项在 list2 中没有对应项,我用默认值填充结果列表的最后一项(在本例中为 0,因为在我的情况下它永远不会出现在任何原始列表)。

有没有办法单独使用linq Zip方法来实现这个?

您可以使用Concat使它们大小相同,然后压缩:

var zipped = list1.Concat(Enumerable.Repeat(0,Math.Max(list2.Count-list1.Count,0)))
        .Zip(list2.Concat(Enumerable.Repeat(0,Math.Max(list1.Count-list2.Count,0))),
            (a,b)=>(a,b));

或者创建一个扩展方法:

public static class ZipExtension{
    public static IEnumerable<TResult> Zip<TFirst,TSecond,TResult>(
        this IEnumerable<TFirst> first,
        IEnumerable<TSecond> second, 
        Func<TFirst,TSecond,TResult> func, 
        TFirst padder1,
        TSecond padder2)
    {
        var firstExp = first.Concat(
            Enumerable.Repeat(
                padder1, 
                Math.Max(second.Count()-first.Count(),0)
            )
        );
        var secExp = second.Concat(
            Enumerable.Repeat(
                padder2,
                Math.Max(first.Count()-second.Count(),0)
            )
        );
        return firstExp.Zip(secExp, (a,b) => func(a,b));
    }
}

所以你可以这样使用:

//last 2 arguments are the padder values for list1 and list2
var zipped = list1.Zip(list2, (a,b) => (a,b), 0, 0); 

试试这个代码-

static void Main(string[] args)
    {
        List<int> firstList=new List<int>() { 1, 2, 3, 4, 5, 6,0,34,56,23};
        List<int> secondList=new List<int>() { 4, 5, 6, 7, 8, 9,1};

        int a = firstList.Count;
        int b = secondList.Count;

        if (a > b)
        {
            for(int k=0;k<(a-b);k++)
                secondList.Add(0);
        }
        else
        {
            for (int k = 0; k < (b-a); k++)
                firstList.Add(0);
        }

        for(int i=0;i<firstList.Count;i++)
        {
            for(int j=0;j<=secondList.Count;j++)
            {
                if(i==j)
                    Console.Write($"({Convert.ToInt32(firstList[i])},{ Convert.ToInt32(secondList[j])})" + "");
            }
        }
        Console.Read();
    }

尝试使用 Zip 功能-

static void Main(string[] args)
    {
        List<int> firstList = new List<int>() { 1, 2, 3, 4, 5, 6, 0, 34, 56, 23 };
        List<int> secondList = new List<int>() { 4, 5, 6, 7, 8, 9, 1 };

        int a = firstList.Count;
        int b = secondList.Count;

        for (int k = 0; k < (a - b); k++)
            {
                if(a>b)
                    secondList.Add(0);
                else
                    firstList.Add(0);
            }

        var zipArray = firstList.Zip(secondList, (c, d) => c + " " + d);
        foreach(var item in zipArray)
        {
            Console.WriteLine(item);
        }
        Console.Read();
    }

或者您可以通过安装 MoreLinq nuget 包使用 ZipLongest 函数来尝试此操作-

static void Main(string[] args)
    {
        List<int> firstList = new List<int>() { 1, 2, 3, 4, 5, 6, 0, 34, 56, 23 };
        List<int> secondList = new List<int>() { 4, 5, 6, 7, 8, 9, 1 };

        var zipArray = firstList.ZipLongest(secondList, (c, d) => (c,d));
        foreach (var item in zipArray)
        {
            Console.WriteLine(item);
        }
        Console.Read();
    }

有一个有用且流行的 MoreLinq 库。安装并使用。

using MoreLinq;
var result = list1.ZipLongest(list2, (x, y) => (x, y));