Получить все пары в списке, используя LINQ - PullRequest
14 голосов
/ 30 августа 2011

Как получить все возможные пары элементов в списке (порядок не имеет значения)?

Например, если у меня есть

var list = { 1, 2, 3, 4 };

Я хотел бы получить следующие кортежи:

var pairs = {
   new Tuple(1, 2), new Tuple(1, 3), new Tuple(1, 4),
   new Tuple(2, 3), new Tuple(2, 4)
   new Tuple(3, 4)
}

Ответы [ 3 ]

24 голосов
/ 30 августа 2011

Небольшая переформулировка cgeers отвечает, чтобы получить нужные кортежи вместо массивов:

var combinations = from item1 in list
                   from item2 in list
                   where item1 < item2
                   select Tuple.Create(item1, item2);

(используйте ToList или ToArray, если хотите.)

В-выражение формы запроса (несколько переупорядочено):

var combinations = list.SelectMany(x => list, (x, y) => Tuple.Create(x, y))
                       .Where(tuple => tuple.Item1 < tuple.Item2);

Оба из них фактически будут учитывать n 2 значений вместо n 2 / 2, хотя онив итоге получу правильный ответ.Альтернативой может быть:

var combinations = list.SelectMany((x, i) => list.Skip(i + 1), (x, y) => Tuple.Create(x, y));

... но при этом используется Skip, который может также не оптимизироваться.Честно говоря, это не имеет значения, я бы выбрал тот, который наиболее подходит для вашего использования.

4 голосов
/ 30 августа 2011

Рассчитайте декартово произведение, чтобы определить все возможные комбинации.

Например:

var combinations = from item in list
                   from item2 in list
                   where item < item2
                   select new[] { item, item2 };

Более подробную информацию о расчете декартового произведения с помощью LINQ можно найти здесь:

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

Затемпреобразовать его в коллекцию объектов Tuple.

var pairs = new List<Tuple<int, int>>();
foreach (var pair in combinations)
{
    var tuple = new Tuple<int, int>(pair[0], pair[1]);
    pairs.Add(tuple);
}

Или коротко:

var combinations = (from item in list
                    from item2 in list
                    where item < item2
                    select new Tuple<int, int>(item, item2)).ToList();
2 голосов
/ 30 августа 2011

Вы можете решить это так:

 var list = new[] { 1, 2, 3, 4 };

 var pairs = from l1 in list
             from l2 in list.Except(new[] { l1 })
             where l1 < l2
             select new { l1, l2 };

 foreach (var pair in pairs)
 {
    Console.WriteLine(pair.l1 + ", " + pair.l2);
 }
...