试图从未知数量的字符串列表中获取所有可能的组合
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...)
给定一个列表列表,我希望创建所有可能的组合。
示例:
我有一个包含 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...)