0

string []配列の一般的なリストがあり、それらの配列内の項目のすべての可能な組み合わせを使用して文字列のリストを作成する必要があります。最善の方法で頭を包むのに苦労しています。

so: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

リストの3番目の配列に1つではなく2つの項目(「フィールド」)がある場合、9つ(3x3x2)ではなく18の文字列のリストがあります。

どの配列が最大の長さであるかを知り、forループを使用して、各リストアイテムをループしようとしましたが、機能させることができませんでした。その上で寝ることは本当に助けにはなりませんでした。

誰でも?

4

3 に答える 3

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;
        }

テスト済みで動作します!

于 2012-10-26T15:53:18.037 に答える
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();
}

可能性のセットごとに、これまでのすべての文字列を取得します (たとえば、「建物---施設---フィールド---ファイル」、「建物---施設---フィールド---エンティティ」など)。 )、次に各可能性 (例: { "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

このソリューションは非常に効率的であることを指摘したいと思います。再帰を使用しないため、チェーンが長い場合に特に効率的です。また、多くの結果の組み合わせを扱う場合は、結果を遅延して評価するため、メモリ効率が大幅に向上します (これらの組み合わせは、チェーンの長さとともに指数関数的に増加する可能性があることに注意してください)。

于 2012-10-26T16:21:17.977 に答える
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

まず、DB からのデータが次の形式であると仮定しましょう。

List<List<string>> dataFromDb;

内部コレクションの一部が 1 つの値しか持たないかどうかは問題ではありません。次に、次のようなものがうまくいくはずです:

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

探しているリストが出力されているはずです。さて、私はこれを実行していないことに注意してください(コンパイルすらしていません)ので、デバッグする必要がありますが、少なくとも正しい方向に進むはずです。

于 2012-10-26T15:50:03.860 に答える