【问题标题】:Words combinations without repetition不重复的单词组合
【发布时间】:2011-07-05 04:51:14
【问题描述】:

我有 10 个单词。如何获得 5 个单词 (n=10, k=5) 的所有可能组合。顺序无关紧要

例如:"A", "B", "C", if k=2 (n=3 in this case),表示 AB、BC 和 AC。也许您知道一些有用的代码或示例。

附:对不起,如果我不够正确,因为我的英语不太好。

【问题讨论】:

    标签: c# string combinations words


    【解决方案1】:

    您要做的是获取集合的所有排列。

    这里是sn-p的代码:

    static void Main(string[] args)
    {
        var list = new List<string> { "a", "b", "c", "d", "e" };
        var result = GetPermutations(list, 3);
        foreach (var perm in result)
        {
            foreach (var c in perm)
            {
                Console.Write(c + " ");
            }
            Console.WriteLine();
        }
        Console.ReadKey();
    }
    
    static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> items, int count)
    {
        int i = 0;
        foreach (var item in items)
        {
            if (count == 1)
                yield return new T[] { item };
            else
            {
                foreach (var result in GetPermutations(items.Skip(i + 1), count - 1))
                    yield return new T[] { item }.Concat(result);
            }
    
            ++i;
        }
    }
    

    输出:

    a b c 
    a b d 
    a b e 
    a c d 
    a c e 
    a d e 
    b c d 
    b c e 
    b d e 
    c d e 
    

    【讨论】:

    【解决方案2】:

    这是我整理的:

    static class LinqExtensions
    {
        public static IEnumerable<IEnumerable<T>> CombinationsWithoutRepetition<T>(
            this IEnumerable<T> items,
            int ofLength)
        {
            return (ofLength == 1) ?
                items.Select(item => new[] { item }) :
                items.SelectMany((item, i) => items.Skip(i + 1)
                                                   .CombinationsWithoutRepetition(ofLength - 1)
                                                   .Select(result => new T[] { item }.Concat(result)));
        }
    
        public static IEnumerable<IEnumerable<T>> CombinationsWithoutRepetition<T>(
            this IEnumerable<T> items,
            int ofLength,
            int upToLength)
        {
            return Enumerable.Range(ofLength, Math.Max(0, upToLength - ofLength + 1))
                             .SelectMany(len => items.CombinationsWithoutRepetition(ofLength: len));
        }
    
    }
    

    ...

    foreach (var c in new[] {"a","b","c","d"}.CombinationsWithoutRepetition(ofLength: 2, upToLength: 4))
    {
        Console.WriteLine(string.Join(',', c));
    }
    

    产生:

    a,b
    a,c
    a,d
    b,c
    b,d
    c,d
    a,b,c
    a,b,d
    a,c,d
    b,c,d
    a,b,c,d
    

    请注意,这很简洁但效率低下,不应该用于大型集合或内部循环。值得注意的是,短数组会被多次重新创建并且可以被记忆,而IEnumerable会被多次迭代,如果不注意可能会导致意外的工作。

    此外,如果输入包含重复项,则输出也将包含重复项。要么先使用.Distinct().ToArray(),要么使用包含相等性检查的其他解决方案,并且大概采用IEqualityComparer 作为通用性。

    【讨论】:

      【解决方案3】:
      public IActionResult Index() 
      {
          var list = new List<string> { "a", "b", "c", "d", "e" };
          List<string> ret = GetAllCombinations(list).OrderBy(_ => _).ToList();
      
          return View();
      }
      
      static IEnumerable<string> GetAllCombinations(IEnumerable<string> list)
      {
          return list.SelectMany((mainItem, mi) => list.Where((otherItem, oi) => mi < oi)
                                    .Select(otherItem => mainItem + otherItem));
      }
      

      输出:

      ab
      ac
      ad
      ae
      bc
      bd
      be
      cd
      ce
      de
      

      【讨论】:

      • 欢迎来到 Stack Overflow。虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。 How to Answer。亲切的问候。
      【解决方案4】:

      更实用的解决方案怎么样

      var list = new List<string> { "a", "b", "c", "d", "e" };
      GetAllCombinations(list).OrderBy(_ => _).ToList().ForEach(Console.WriteLine);
      
      
      static IEnumerable<string> GetAllCombinations(IEnumerable<string> list)
      {
          return list.SelectMany(mainItem => list.Where(otherItem => !otherItem.Equals(mainItem))
                                    .Select(otherItem => mainItem + otherItem));
      }
      

      输出:

      ab
      ac
      ad
      ae
      ba
      bc
      bd
      be
      ca
      cb
      cd
      ce
      da
      db
      dc
      de
      ea
      eb
      ec
      ed
      

      【讨论】:

      • OP指定顺序无关紧要,因此出现在该代码结果中的“ab”和“ba”是相同的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-13
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多