使用LINQ获取列表中的所有对

时间:2011-08-30 10:48:37

标签: c# linq tuples combinations

如何在列表中获取所有可能的项目对(顺序不相关)?

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

3 个答案:

答案 0 :(得分:23)

cgeers的轻微重新设计回答为你提供你想要的元组而不是数组:

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

(如果需要,请使用ToListToArray。)

以非查询表达式形式(稍微重新排序):

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