Linq возвращает ВСЕ пары элементов из двух списков?

Данные списки l1 = {1 , 2} и l2 = {4, 5, 6} Я хочу получить новый список с элементами:

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

Предложения?

16
задан Cristi Diaconescu 26 August 2010 в 14:09
поделиться

7 ответов

Да, это возможно. Эрик Липперт написал очень хорошую статью на эту тему:

Вычисление декартова произведения с помощью LINQ

Если у вас есть только 2 списка, вы можете напрямую использовать несколько из следующим образом:

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

или даже:

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

Но решение, данное Эриком Липпертом в предыдущей статье, позволяет вычислить декартово произведение нескольких последовательностей. С помощью следующего метода расширения:

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

Вы можете написать:

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

И получить:

{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}
30
ответ дан 30 November 2019 в 16:36
поделиться

Эрик Липперт уже сделал это за вас!

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

вы, вероятно, просто хотите использовать свободный синтаксис linq из SelectMany

var s1 = new[] {a, b}; 
var s2 = new[] {x, y, z}; 


var product = 
from first in s1 
from second in s2 
select new[] { first, second };

product.SelectMany(o=>o);

или сообщение в блоге Эрика version

static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences) 
{ 
  // base case: 
  IEnumerable<IEnumerable<T>> result = new[] { Enumerable.Empty<T>() }; 
  foreach(var sequence in sequences) 
  { 
    var s = sequence; // don't close over the loop variable 
    // recursive case: use SelectMany to build the new product out of the     old one 
    result = 
      from seq in result 
      from item in s 
      select seq.Concat(new[] {item}); 
  } 
  return result; 
}

product.CartesianProduct();

4
ответ дан 30 November 2019 в 16:36
поделиться

Вы хотите

l1.Join(l2, a => 1, b => 1, (a, b) => new [] { a, b });
-3
ответ дан 30 November 2019 в 16:36
поделиться

что-то вроде этого сделает то, что вы ищете.

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

с этим ответом ваши кортежи {x,y} являются анонимными.

1
ответ дан 30 November 2019 в 16:36
поделиться

Вот, пожалуйста;

var rez =  from first in l1 
           from second in l2 
           select new[] { first, second };
2
ответ дан 30 November 2019 в 16:36
поделиться

Отличная статья Эрика Липперта - см. ссылки в других ответах. Что еще лучше, это была первая попытка, которую я предпринял до просмотра ответов на этой странице :)

Вкратце:

var rez = 
    from e1 in l1
    from e2 in l2 
    select new {e1, e2};
1
ответ дан 30 November 2019 в 16:36
поделиться
var result = from a in l1
             from b in l2
             select new[] { a, b }
3
ответ дан 30 November 2019 в 16:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: