试图从未知数量的字符串列表中获取所有可能的组合

Trying to get all possible combinations from an unknown number of list of strings

给定一个列表列表,我希望创建所有可能的组合。

示例:

我有一个包含 3 个列表的列表

列表 1:苹果、香蕉、梨

列表 2:床、椅子

名单 3:本、鲍勃、卡尔、菲尔

由此我希望得到一个组合列表

Apple_Bed_Ben

Apple_Bed_Bob

Apple_Bed_Carl

Apple_Bed_Phil

Apple_Chair_Ben

Apple_Chair_Bob

Apple_Chair_Carl

Apple_Chair_Phil

Banana_Bed_Ben

Banana_Bed_Bob

...

我不知道我是否遗漏了什么,但我已经转了几个小时了。

如果我知道只会有三个列表,我知道我可以使用嵌套的 for 循环来构建组合字符串,但这里可以有任意数量的列表。

任何人都可以指出正确的方向来完成这项工作吗?

这是我目前拥有的:

public class ChildrenNames
{
    public string parentName;
    public int numberOfNames;
    public List<string> childrenNames = new List<string>();
}

public class Combination
{
    public bool selected = true;
    public string name;
}

List<Combination> GetAllCombinations()
{
    List<Combination> allCombinations = new List<Combination>();
    List<ChildrenNames> listOfChildren = new List<ChildrenNames>();

    //Create list of children names for each parent object
    for (int p = 0; p < parentObjects.Count; p++)
    {
        ChildrenNames cn = new ChildrenNames();

        for (int c = 0; c < parentObjects[p].transform.childCount; c++)
            cn.childrenNames.Add(parentObjects[p].transform.GetChild(c).name);

        cn.parentName = parentObjects[p].name;
        cn.numberOfNames = cn.childrenNames.Count;
        listOfChildren.Add(cn);
    }

    for (int l = 0; l < listOfChildren.Count; l++)
    {
        for (int c = 0; c < listOfChildren[l].numberOfNames; c++)
        {
            if (l == 0)
            {
                for (int p  = 0; p  < listOfChildren.Count; p ++)
                {
                    Combination combination = new Combination();
                    combination.name = listOfChildren[l].childrenNames[c];
                    allCombinations.Add(combination);
                }

            }
            else
            {
                for (int i = 0; i < allCombinations.Count; i++)
                    allCombinations[i].name += "_" + listOfChildren[l].childrenNames[c];
            }
        }

    }

    return allCombinations;
}

这创建了正确数量的组合,但例如抛出了

Apple_Bed_Chair_Ben_Bob_Carl_Phil

我明白为什么会这样,但不知道如何改变它以获得预期的结果。

您需要跟踪每个列表的列以使其正常工作。

public List<string> ZipStringLists(params List<string>[] lists)
{
    var columnNo = new int[lists.Length];
    var resultingList = new List<string>();
    var stringBuilder = new StringBuilder();

    while (columnNo[0] < lists[0].Count)
    {
        // Combine the items into one: Apple + Banana + Pear = AppleBananaPear
        for (int i = 0; i < lists.Length; i++)
        {
            var listElement = lists[i];
            // columnNo[i] contains which column to write out for the individual list
            stringBuilder.Append(listElement[columnNo[i]]);
        }

        // Write out the result and add it to a result list for later retrieval
        var result = stringBuilder.ToString();
        resultingList.Add(result);
        Console.WriteLine(result);
        stringBuilder.Clear();

        // We increment columnNo from the right to the left
        // The next item after AppleBedBen is AppleBedBob
        // Overflow to the next column happens when a column reaches its maximum value 
        for (int i = lists.Length - 1; i >= 0; i--)
        {
            if (++columnNo[i] == lists[i].Count 
                    && i != 0 /* The last column overflows when the computation finishes */)
            {
                // Begin with 0 again on overflow and continue to add to the next column
                columnNo[i] = 0;
            }
            else
            {
                // No overflow -> stop
                break;
            }
        }

    }

    return resultingList;
}

用法:

List<string> list1 = new List<string> { "Apple", "Banana", "Pear" };
List<string> list2 = new List<string> { "Bed", "Chair" };
List<string> list3 = new List<string> { "Ben", "Bob", "Carl", "Phil" };

ZipStringLists(list1, list2, list3);

您可以使用接受任意数量列表的相当通用的解决方案来逐步构建组合。它很短,但不一定像其他解决方案那样优化,因为它构建了中间列表:

    public List<string> FindCombinations(params List<string>[] lists)
    {
        List<string> combinations = lists[0];

        for (int i = 1; i < lists.Length; i++)
        {
            List<string> newCombinations = new List<string>(combinations.Count * lists[i].Count);
            combinations.ForEach(s1 => lists[i].ForEach(s2 => newCombinations.Add($"{s1}_{s2}")));
            combinations = newCombinations;
        }

        return combinations;
    }

用法:

   List<string> combinations = FindCombinations(list1, list2, list3, list4, list5...)