为字符串列表生成所有组合

Posted

技术标签:

【中文标题】为字符串列表生成所有组合【英文标题】:Generate all combinations for a list of strings 【发布时间】:2012-05-17 22:19:58 【问题描述】:

我想生成一个字符串列表的所有可能组合的列表(它实际上是一个对象列表,但为简单起见,我们将使用字符串)。我需要这个列表,以便我可以在单元测试中测试所有可能的组合。

例如,如果我有一个列表:

  var allValues = new List<string>()  "A1", "A2", "A3", "B1", "B2", "C1" 

我需要一个 List&lt;List&lt;string&gt;&gt; 以及所有组合,例如:

  A1
  A2
  A3
  B1
  B2
  C1
  A1 A2
  A1 A2 A3
  A1 A2 A3 B1
  A1 A2 A3 B1 B2
  A1 A2 A3 B1 B2 C1
  A1 A3
  A1 A3 B1
  etc...

递归函数可能是获得所有组合的方法,但它似乎比我想象的要难。

任何指针?

谢谢。

编辑:两种解决方案,带或不带递归:

public class CombinationGenerator<T>

    public IEnumerable<List<T>> ProduceWithRecursion(List<T> allValues) 
    
        for (var i = 0; i < (1 << allValues.Count); i++)
        
            yield return ConstructSetFromBits(i).Select(n => allValues[n]).ToList();
        
    

    private IEnumerable<int> ConstructSetFromBits(int i)
    
        var n = 0;
        for (; i != 0; i /= 2)
        
            if ((i & 1) != 0) yield return n;
            n++;
        
    

    public List<List<T>> ProduceWithoutRecursion(List<T> allValues)
    
        var collection = new List<List<T>>();
        for (int counter = 0; counter < (1 << allValues.Count); ++counter)
        
            List<T> combination = new List<T>();
            for (int i = 0; i < allValues.Count; ++i)
            
                if ((counter & (1 << i)) == 0)
                    combination.Add(allValues[i]);
            

            // do something with combination
            collection.Add(combination);
        
        return collection;
    

【问题讨论】:

我知道这不是您想要的,但微软有这个系统处于测试阶段,它会自动为您生成输入组合。它被称为 Pex:research.microsoft.com/en-us/projects/pex 想象一个二进制计数器。这应该可以帮助您入门。 Listing all permutations of a string/integer的可能重复 你不需要递归:***.com/questions/10331229/… 确实,甚至不需要递归,太好了! 【参考方案1】:

您可以手动输入,利用 n 位二进制数自然对应 n 元素集的子集这一事实。

private IEnumerable<int> constructSetFromBits(int i)

    for (int n = 0; i != 0; i /= 2, n++)
    
        if ((i & 1) != 0)
            yield return n;
    


List<string> allValues = new List<string>()
         "A1", "A2", "A3", "B1", "B2", "C1" ;

private IEnumerable<List<string>> produceEnumeration()

    for (int i = 0; i < (1 << allValues.Count); i++)
    
        yield return
            constructSetFromBits(i).Select(n => allValues[n]).ToList();
    


public List<List<string>> produceList()

    return produceEnumeration().ToList();

【讨论】:

【参考方案2】:

如果您想要所有变体,请查看此项目以了解其实施方式。

http://www.codeproject.com/Articles/26050/Permutations-Combinations-and-Variations-using-C-G

但是你可以使用它,因为它是在CPOL 下开源的。

例如:

var allValues = new List<string>()  "A1", "A2", "A3", "B1", "B2", "C1" ;
List<String> result = new List<String>();
var indices = Enumerable.Range(1, allValues.Count);
foreach (int lowerIndex in indices)

    var partVariations = new Facet.Combinatorics.Variations<String>(allValues, lowerIndex);
    result.AddRange(partVariations.Select(p => String.Join(" ", p)));


var length = result.Count;  // 1956

【讨论】:

【参考方案3】:

在下面的帖子中完成了类似的任务:

Listing all permutations of a string/integer

希望对您有所帮助。

【讨论】:

在 Stack Overflow 上不鼓励仅链接的答案,因为链接可能会中断,并且链接到的资源可能会更改。请考虑在此处总结链接的相关部分。 另外,您链接到的答案是生成排列,这不是一回事 作为组合【参考方案4】:

一个更递归的解决方案。从下面代码中的AllCombinations,您将获得所有可能的组合。 逻辑:

    从一个元素开始。 用它生成所有可能的组合。 移至下一个元素并再次从第 2 步开始。

代码:

public class Combination<T>

    private IEnumerable<T> list  get; set; 
    private int length;
    private List<IEnumerable<T>> _allCombination;

    public Combination(IEnumerable<T> _list)
    
        list = _list;
        length = _list.Count();

        _allCombination = new List<IEnumerable<T>>();
    

    public IEnumerable<IEnumerable<T>> AllCombinations
    
        get
        
            GenerateCombination(default(int), Enumerable.Empty<T>());

            return _allCombination;
        
    

    private void GenerateCombination(int position, IEnumerable<T> previousCombination)
    
        for (int i = position; i < length; i++)
        
            var currentCombination = new List<T>();
            currentCombination.AddRange(previousCombination);
            currentCombination.Add(list.ElementAt(i));

            _allCombination.Add(currentCombination);

            GenerateCombination(i + 1, currentCombination);

        
    

【讨论】:

以上是关于为字符串列表生成所有组合的主要内容,如果未能解决你的问题,请参考以下文章

生成所有槽数未知的组合

从字符串生成子字符串的组合

生成所有可能的组合

获取字符串或组合的所有可能排列,包括 Java 中的重复字符

生成字符串的所有组合的算法

使用一组字符串生成所有可能的组合