【问题标题】:C# LINQ combinatorics: All Combinations of a Set without the Empty SetC# LINQ 组合:没有空集的集合的所有组合
【发布时间】:2015-05-06 16:02:14
【问题描述】:

我有一组字符串,我想找到所有可能的字符串组合并将它们添加到列表中。我想得到一个字符串的每个组合的列表,减去空集。

我已经创建了一个解决方案,它完全使用嵌套的 for 循环来执行此操作。但是我想更优雅地做到这一点,最好使用 LINQ,但我对它还不是很熟练,因为我对它还是很陌生。

解决方案应该有 2^n - 1 个组合列表,其中 n 是原始集合的基数。这是我正在寻找的正确示例:

set = {a, b, c}

completedListOfCombinations = 
{
    {a},
    {b},
    {a, b},
    {c},
    {a, c},
    {b, c},
    {a, b, c}
}

这是我在以下人员的帮助下制定的可行的、基本但丑陋的解决方案:https://stackoverflow.com/a/3319652/3371287

List<string> myStrings =  new List<string> { "a", "b", "c" };

var allCombos = new List<List<string>>();

for (int i = 0; i < myStrings.Count; i++)
{
    int subsetCount = allCombos.Count;
    var m = new List<string>();
    m.Add(myStrings[i]);
    allCombos.Add(m);

    for (int j = 0; j < subsetCount; j++)
    {
        string[] subset = new string[allCombos.ElementAt(j).Count + 1];
        allCombos[j].CopyTo(subset, 0);
        subset[subset.Length - 1] = myStrings[i];
        allCombos.Add(subset.ToList());
    }

}

有人可以向我展示一个更优雅的解决方案吗?我见过类似的 LINQ 解决方案,它们创建笛卡尔对和具有阈值的列表,但我无法将它们调整到我需要的。

【问题讨论】:

标签: c# linq combinatorics


【解决方案1】:

假设list 中的所有值都是唯一

  List <String> list = new List<String> { "a", "b", "c" };

  var result = Enumerable
    .Range(1, (1 << list.Count) - 1)
    .Select(index => list.Where((item, idx) => ((1 << idx) & index) != 0).ToList());

打印出来:

Console.WriteLine(String
  .Join(Environment.NewLine, result
     .Select(line => String.Join(", ", line))));

结果是

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

【讨论】:

  • 是的,列表中的值始终是唯一的。做得好!我想剖析和理解这一点。
  • 你可以认为它是从 1 数到 2^n-1。如果您查看二进制索引 (001 -> 010 -> 011 -> 100 -> 101 -> 110 -> 111),然后将每个二进制数字映射到您的列表值之一 ("a","b"," c"),并且只显示为 1 的那些(我会将 0 显示为 0,而不是根本不显示它们),然后你会得到 (00a, 0b0, 0ba, c00, c0a, cb0, cba)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-19
  • 2012-03-27
  • 1970-01-01
  • 2013-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多