【问题标题】:Best way to enumerate all combinations枚举所有组合的最佳方法
【发布时间】:2020-01-25 01:24:12
【问题描述】:

假设我有以下任意顺序的列表:

S1 
R1 
R2 
S2
S3

我需要创建一个列表,其中每个“S”包含每个“R”组合

输出:

S1 => R1
S1 => R2
S2 => R1
S2 => R2
S3 => R1
S3 => R2

实现这一目标的最佳方法是什么? 谢谢

【问题讨论】:

  • 这听起来像是 2 个列表,而不是一个。您希望将 S 列表中的所有元素与 R 列表组合在一起。以这种方式思考会使工作像嵌套循环一样简单。
  • 为 R 元素解析列表以移动到另一个列表,O(n)。对于剩余的每个 S,构建一个字典,其中每个 S 元素都指向与元素 R 相同的列表。
  • 听起来像“笛卡尔积” (stackoverflow.com/questions/1741364/…) - 不确定这是否是您所要求的。
  • 对我来说听起来像 MS SQL 的“select * from table1, table2”,不是吗?还是没有?

标签: c# .net


【解决方案1】:

试试:

var byPrefix = list.GroupBy(i => i.First()).ToDictionary(g => g.Key, g => g);
var result = 
    from s in byPrefix['S']
    from r in byPrefix['R']
    select new { s, r };

【讨论】:

  • SelectMany 救援
  • ToDictionary 允许索引访问并避免冗余迭代。
  • 是的,我意识到如果没有它,这比我想象的要难:)
【解决方案2】:

正如 Pranav 和 huseyin 提到的,您只需拆分为两个列表,然后使用嵌套的 foreach 循环遍历它们。

var startingList = new List<string> { "S1", "R1", "R2", "S2", "S3" };
List<Tuple<string, string>> result = new List<Tuple<string, string>>();

foreach(var s in startingList.Where(x => x.StartsWith("S")).ToList())
{
    foreach(var r in startingList.Where(x => x.StartsWith("R")).ToList())
    {
        result.Add(new Tuple<string, string>(s, r));
    }
}

【讨论】:

    【解决方案3】:

    这是我想出的,数组和枚举数的混合体:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace ConsoleApplication2
    {
        class Program
        {
            static void Main(string[] args)
            {
                var input = new string[] {
                    "S1", 
                    "R1", 
                    "R2", 
                    "S2",
                    "S3"
                };
                foreach (var item in CombinationsOfSAndR(input)) 
                {
                    Console.WriteLine("{0} -> {1}", item.Key, item.Value);
                }
                /* OUT:
                S1 -> R1
                S1 -> R2
                S2 -> R1
                S2 -> R2
                S3 -> R1
                S3 -> R2 */
            }
            static IEnumerable<KeyValuePair<string, string>> CombinationsOfSAndR(string[] input)
            {
                for (int i = 0; i < input.Length; i++)
                {
                    if (input[i].StartsWith("S"))
                    {
                        for (int j = 0; j < input.Length; j++)
                        {
                            if (input[j].StartsWith("R"))
                            {
                                yield return new KeyValuePair<string, string>(input[i], input[j]);
                            }
                        }
                    }
                }
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      如果这总是静态的,我的意思是总是两个列表(或前缀),你可以做嵌套循环:

      List<string> list = new List<string>();
      list.Add("S1");
      list.Add("R1");
      list.Add("R2");
      list.Add("S2");
      list.Add("S3");
      

      循环

      foreach (var s in list.Where(l => l.StartsWith("S")))
      {
          foreach (var r in list.Where(l => l.StartsWith("R")))
          {
              Console.WriteLine(string.Format("{0} => {1}", s, r));
          }
      }
      

      或:

      list.Where(l => l.StartsWith("S"))
          .ToList()
          .ForEach(s => list.Where(l => l.StartsWith("R"))
                            .ToList()
                            .ForEach(r => Console.WriteLine(string.Format("{0} => {1}", s, r)))
                  );
      

      您可以将结果添加到另一个列表,而不是 Console.WriteLine

      【讨论】:

        猜你喜欢
        • 2012-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多