Adolfo Perez
Adolfo Perez

Reputation: 2874

How to combine multiple lists of same or different lengths in Linq?

I would like to build a method or extension method that takes multiple lists and combines them in the following way:

Lets say i have two lists:

        int[] list1 =  {3, 1, 2};
        int[] list2 =  {5, 4 };

I would expect a list of arrays as a result like this:

[1,4]
[1,5]
[2,4]
[2,5]
[3,4]
[3,5]

The number of columns in my resulting list of arrays would be determined by the amount of lists passed and both columns need to be sorted. The number of rows is just the (length of list A) * (length of list B) * (length of list N)

In this example is 3 * 2 = 6 rows. 2 columns (because 2 input lists).

What would be an elegant way of doing this with linq?

Thanks!

Upvotes: 1

Views: 1426

Answers (3)

Adolfo Perez
Adolfo Perez

Reputation: 2874

Credit goes here to @Jon for pointing me to the right source and @EricLippert for his clever solution:

    public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences)
    {
        IEnumerable<IEnumerable<T>> emptyProduct =
          new[] { Enumerable.Empty<T>() };
        return sequences.Aggregate(
          emptyProduct,
          (accumulator, sequence) =>
            from accseq in accumulator
            from item in sequence
            select accseq.Concat(new[] { item }));
    }

http://ericlippert.com/2010/06/28/computing-a-cartesian-product-with-linq/

Works nice with ints and strings:

        string[] list1 =  {"1", "2", "3"};
        string[] list2 =  { "4","5" };

        var lists = new List<string[]>(){list1,list2};

        var result = lists.CartesianProduct();

Upvotes: 2

Tilak
Tilak

Reputation: 30698

Try cross join

int[] list1 =  {3, 1, 2};
int[] list2 =  {5, 4 }; 

var result = (from l1 in list1
             from l2 in list2
             select new [] {l1, l2}).ToList()

Upvotes: 3

Jon
Jon

Reputation: 437376

Use SelectMany:

var combinations = list1.SelectMany(i1 => list2.Select(i2 => new[] { i1, i2 }));

or if you prefer

var combinations = list1.SelectMany(i1 => list2, (i1, i2) => new[] { i1, i2 });

If you want to get the results in a specific order you can follow this up with OrderBy etc.

Upvotes: 2

Related Questions