C#字符串连接具有n ^ n种可能性

时间:2012-10-26 15:15:43

标签: c# string arraylist concatenation

我有一个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循环,知道哪个数组的长度最大,并遍历每个列表项,但我无法让它工作。睡在上面并没有真正的帮助。

3 个答案:

答案 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);

您要查找的列表应该在输出中。现在,请注意,我没有运行这个(哎呀,我甚至没有编译过这个)所以你需要调试它,但它应该让你至少在正确的方向上进行。