繁体   English   中英

具有n ^ n种可能性的C#字符串串联

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM