Reputation: 406
I have two C# Lists of different sizes e.g.
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};
I want to use the linq Zip method to combine these two into a list of tuples that is of the size list1. Here is the resulting list I am looking for
{(1,4), (2,5), (3,6), (4,7), (5,8), (6,9), (7,0)} //this is of type List<(int,int)
Since the last item of list1 does not has a counterpart in list2, I fill up my last item of the resulting list with a default value (in this case 0 as in my case it will never appear in any of the original lists).
Is there a way I can use the linq Zip method alone to achieve this?
Upvotes: 2
Views: 1945
Reputation: 11
Try this using Zip function-
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();
}
Or you can try this using ZipLongest Function by installing MoreLinq nuget package-
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();
}
Upvotes: 1
Reputation: 14231
There is a useful and popular MoreLinq library. Install it and use.
using MoreLinq;
var result = list1.ZipLongest(list2, (x, y) => (x, y));
Upvotes: 2
Reputation: 11
Try this code-
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();
}
Upvotes: 0
Reputation: 8543
You can use Concat
to make them both the same size, and then zip it:
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));
Or create an extension method:
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));
}
}
So you can use like this:
//last 2 arguments are the padder values for list1 and list2
var zipped = list1.Zip(list2, (a,b) => (a,b), 0, 0);
Upvotes: 3