tags:

views:

185

answers:

7

Given lists l1 = {1, 2} and l2 = {4, 5, 6 } I want to get a new list that has elements:

rez = { {1, 4}, {1, 5}, {1, 6}, {2, 4}, {2, 5}, {2, 6} }

Suggestions?

+5  A: 

Eric Lippert's already done it for you!

http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/computing-a-cartesian-product-with-linq.aspx

Graham Clark
+20  A: 

Yes it is possible. Eric Lippert wrote a very good article on this topic:

Computing a Cartesian Product with LINQ

If you only have 2 lists, then you could directly use multiple from like this:

from a in s1 
from b in s2 
select new [] { a, b};

or even:

s1.SelectMany(a => s2.Select(b => new [] { a, b }));

But the solution given by Eric Lippert in the previous article allows you to compute the cartesian product of several sequences. With the following extension method:

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 }));
}

You could write:

var l1 = new[] {1, 2};
var l2 = new[] {4, 5, 6};
var l3 = new[] {7, 3};

foreach (var result in new []{l1,l2,l3}.CartesianProduct())
{
    Console.WriteLine("{"+string.Join(",",result)+"}");
}

And obtain:

{1,4,7}
{1,4,3}
{1,5,7}
{1,5,3}
{1,6,7}
{1,6,3}
{2,4,7}
{2,4,3}
{2,5,7}
{2,5,3}
{2,6,7}
{2,6,3}
Romain Verdier
A: 

You want

l1.Join(l2, a => 1, b => 1, (a, b) => new [] { a, b });
Jader Dias
what's the join for?
Cristi Diaconescu
Join is not necessary for this operation and might even create a bit more overhead (don't quote me on that last part). The other answers demonstrate something more intuitive.
Anthony Pegram
it works, period
Jader Dias
Sure, it works, but this is a completely unnecessary abuse of the join sequence operator. The purpose of the join sequence operator is to efficiently perform filtering operations on the Cartesian product, but you are using it here to explicitly do *no filtering*. This means that all the mechanisms inside the implementation of Join which are designed to ensure efficient filtering are now working *against* you rather than *for* you. If you want to do a simple unfiltered Cartesian product, we provide the SelectMany sequence operator to do that. *Use the right tool for the job.*
Eric Lippert
+3  A: 
var result = from a in l1
             from b in l2
             select new[] { a, b }
Justin Niessner
+4  A: 

Here you go;

var rez =  from first in l1 
           from second in l2 
           select new[] { first, second };
NetSide
+1  A: 

Great article by Eric Lippert - see links in other answers. What's even better, this was the first try I did before looking at the answers on this page :)

In short:

var rez = 
    from e1 in l1
    from e2 in l2 
    select new {e1, e2};
Cristi Diaconescu
+1  A: 

Hi there, something like this will do what you are looking for.

var l1 = new List<int>{1,2};
var l2 = new List<int>{4,5,6};

var p = from n in l1
        from m in l2
        select new { Fst = n, Scd = m };

with this answer your tuples {x,y} are an anonymous type.

cirons42