[英]C# string concatenation with n^n possibilities
我有一个string []数组的通用列表,我需要使用这些数组中各项的所有可能组合来构建一个字符串列表。 我很难用最好的方法来解决问题。
所以:List mylist = new List; //然后从数据库中填充它...
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
如果列表中的第三个数组有2个项目,而不是1个(“字段”)-我们将有18个字符串的列表,而不是9个(3x3x2)。
我尝试使用for循环,知道哪个数组的长度最大,并遍历每个列表项,但是我无法使其工作。 睡在它上并没有真正的帮助。
任何人?
我会尝试递归:
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;
}
经过测试,可以正常工作!
我认为这可能会满足您的需求:
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();
}
对于每种可能性,它都会使用到目前为止的所有字符串(例如“建筑物---设施---字段---文件”,“建筑物---设施---字段---实体”等),然后针对每种可能性(例如{“ 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
我想指出,这种解决方案非常有效。 它不使用递归,这使得它在长链情况下特别有效。 而且,它懒惰地评估结果,如果您要处理许多结果组合(请记住这些组合可以随着链长成指数增长),那么它的内存效率更高。
让我们产生这个代替:
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);
您要查找的列表应该在输出中。 现在,请注意,我还没有运行它(哎呀,我什至还没有编译它),所以您需要对其进行调试,但它至少可以使您朝正确的方向前进。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.