我有一个string []数组的通用列表,我需要构建一个字符串列表,其中包含这些数组中项目的所有可能组合。我很难绕过最好的方法。
所以: 列表mylist =新列表; //然后我从db ...
填充这个mylist的内容如下所示:
Buildings ||| Facilities ||| Fields ||| Files; Groups; Entity; ||| Controllers; FX; Steam;
管道“|||”将mylist中的每个字符串数组分开,分号是分隔符,表示每个数组中的项目。因此,数组的最小长度为1,最大值为N.我需要构建一个连字符“---”分隔字符串的列表,其中包含上述所有可能的组合,但保持它们在名单。因此,以上面的例子为例,我想出了这个字符串列表:
Buildings---Facilities---fields---Files---Controllers
Buildings---Facilities---fields---Groups---Controllers
Buildings---Facilities---fields---Entity---Controllers
Buildings---Facilities---fields---Files---Fx
Buildings---Facilities---fields---Groups---Fx
Buildings---Facilities---fields---Entity---Fx
Buildings---Facilities---fields---Files---Steam
Buildings---Facilities---fields---Groups---Steam
Buildings---Facilities---fields---Entity---Steam
如果列表中的第3个数组有2个项目而不是1个(“字段”) - 我们有一个包含18个字符串而不是9个字符串(3x3x2)的列表。
我尝试使用for循环,知道哪个数组的长度最大,并遍历每个列表项,但我无法让它工作。睡在上面并没有真正的帮助。
人
答案 0 :(得分:2)
我会尝试递归:
private void button1_Click(object sender, EventArgs e)
{
List<string[]> strs = new List<string[]>();
strs.Add(new string[] {"Buildings"});
strs.Add(new string[] {"Facilities"});
strs.Add(new string[] {"Fields"});
strs.Add(new string[] {"Files", "Groups", "Entity"});
strs.Add(new string[] {"Controllers", "FX", "Steam"});
List<string> list = AddStringsToList(strs, 0);
}
List<string> AddStringsToList(List<string[]> list, int level)
{
List<string> listOfStrings = new List<string>();
if (level == list.Count - 1)
{
foreach (string s in list[level])
{
listOfStrings.Add(s);
}
}
else if(level<list.Count-1)
{
List<string> list1 = AddStringsToList(list, level + 1);
foreach (string s in list[level])
{
foreach(string s1 in list1)
listOfStrings.Add(s + "---" + s1);
}
}
return listOfStrings;
}
经过测试,确实有效!
答案 1 :(得分:2)
我认为这可能会做你想要的:
static IEnumerable<string> Combinations(IEnumerable<IEnumerable<string>> items)
{
return items.Aggregate((outs, ins) => outs.SelectMany(o => ins.Select(i => o + "---" + i)));
}
这是一个示例用法
static void Main(string[] args)
{
IEnumerable<IEnumerable<string>> items = new string[][]
{
new [] { "Buildings" },
new [] { "Facilities" },
new [] { "Fields" },
new [] { "Files", "Groups", "Entity" },
new [] { "Controllers", "FX", "Steam" }
};
foreach (var c in Combinations(items))
Console.WriteLine(c);
Console.ReadLine();
}
对于每一种可能性,它需要它到目前为止所有的字符串(例如“建筑---设施---字段---文件”,“建筑物---设施---字段---”实体“etc”,然后对于每种可能性(例如{“Controllers”,“FX”,“Steam”}),它将这种可能性附加到输出字符串以获得一组新的输出字符串。聚合迭代此过程,从第一个元素作为输出字符串的可能性开始,然后连续重复此“笛卡尔积”,直到所有输入都被消耗。
修改强>
作为参考,这是示例程序的输出:
Buildings---Facilities---Fields---Files---Controllers
Buildings---Facilities---Fields---Files---FX
Buildings---Facilities---Fields---Files---Steam
Buildings---Facilities---Fields---Groups---Controllers
Buildings---Facilities---Fields---Groups---FX
Buildings---Facilities---Fields---Groups---Steam
Buildings---Facilities---Fields---Entity---Controllers
Buildings---Facilities---Fields---Entity---FX
Buildings---Facilities---Fields---Entity---Steam
我想指出这个解决方案非常有效。它不使用递归,这使得它对于具有长链的情况特别有效。此外,它会懒惰地评估结果,如果您处理许多结果组合,则会更加节省内存(请记住,这些组合可以随着链长呈指数增长)。
答案 2 :(得分:0)
让我们来代替:
Buildings---Facilities---fields---Files---Controllers
Buildings---Facilities---fields---Files---Fx
Buildings---Facilities---fields---Files---Steam
Buildings---Facilities---fields---Groups---Controllers
Buildings---Facilities---fields---Groups---Fx
Buildings---Facilities---fields---Groups---Steam
Buildings---Facilities---fields---Entity---Controllers
Buildings---Facilities---fields---Entity---Fx
Buildings---Facilities---fields---Entity---Steam
首先,我们假设数据库中的数据采用以下格式:
List<List<string>> dataFromDb;
如果某些内部集合只有一个值,则无关紧要。那么这样的事情应该可以解决问题:
void ConcatString(string prefix, int index, List<List<string>> collection, List<string> output)
{
if(index == collection.Count)
{
output.Add(prefix);
return;
}
var subCollection = collection[index];
foreach(var str in subCollection)
{
string newPrefix = ((prefix.Length > 0)? "---" : "") + str;
ConcatString(newPrefix, index+1, collection, output);
}
}
叫做:
var output = new List<string>();
ConcatString("", 0, dataFromDb, output);
您要查找的列表应该在输出中。现在,请注意,我没有运行这个(哎呀,我甚至没有编译过这个)所以你需要调试它,但它应该让你至少在正确的方向上进行。