【问题标题】:Get all pairs in a list using LINQ使用 LINQ 获取列表中的所有对
【发布时间】:2011-11-06 16:58:40
【问题描述】:

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

例如如果我有

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, 1, 1, 1 } 列表的期望输出是什么?六个(1, 1) 还是一个(1, 1)

标签: c# linq tuples combinations


【解决方案1】:

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

这两个实际上都会考虑 n2 个值而不是 n2/2 个值,尽管它们最终会得到正确的答案。另一种选择是:

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

...但这使用了Skip,可能没有被优化。老实说,这可能无关紧要 - 我会选择最适合您使用的那个。

【讨论】:

  • Jon,这将创建Tuple (1,1),它不是一对。
  • 谢谢,这是最好的解决方案。 (但是,你的意思是Skip(x.index + 1)?)
  • 是的,Except(..) 是不必要的,因为 where 子句负责处理。
【解决方案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();

【讨论】:

  • 1. 这将创建一个可枚举的列表。这真的是你的意思吗?为什么不只是select Tuple.Create(item, item2)2. 这将导致重复对,例如(1,4)(4,1)。不确定这是否是 OP 想要的,但看起来不像。
  • 它还会创建(1,1),这在OPs示例中没有说明,也不是一对。但我想知道(1,4)(4,1) 是否重要。
  • @stakx @Mikael 所有重复的都可以被where item &lt; item2过滤掉。
  • 感谢您的反馈。更新了我的答案以过滤掉重复项。
  • @Laroslav 仅当项目是为了开始,对吧?
【解决方案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);
 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-18
    • 1970-01-01
    • 2011-03-17
    • 1970-01-01
    • 2012-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多