如何在列表中获取所有可能的项目对(顺序不相关)?
E.g。如果我有
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)
}
答案 0 :(得分:23)
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.Select((value, index) => new { value, index })
.SelectMany(x => list.Skip(x.index + 1),
(x, y) => Tuple.Create(x.value, y));
...但这会使用Skip
,但 也可能未经优化。说实话,这可能没关系 - 我会选择最合适的用途。
答案 1 :(得分:4)
计算笛卡尔积以确定所有可能的组合。
例如:
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 :(得分:2)
你可以这样解决:
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);
}