Получить все пары в списке, используя LINQ
Как получить все возможные пары элементов в списке (не обязательно)?
например. если у меня есть
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)
}
Ответы
Ответ 1
Небольшая переформулировка 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);
Оба они будут фактически рассматривать п 2 значения вместо 2/2 значений п, хотя они в конечном итоге с правильным ответом. Альтернативой будет:
var combinations = list.SelectMany((x, i) => list.Skip(i + 1), (x, y) => Tuple.Create(x, y));
... но при этом используется Skip
который также нельзя оптимизировать. Честно говоря, это не имеет значения, я бы выбрал тот, который наиболее подходит для вашего использования.
Ответ 2
Вычислить декартово произведение для определения всех возможных комбинаций.
Например:
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();
Ответ 3
Вы можете решить это следующим образом:
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);
}