LINQを使用した組み合わせの反復

可能重複:
  可能な組み合わせをすべて生成
  デカルトを行うには良いLINQ方法がありますか?商品ですか?
  組み合わせを生成する方法明示的にネストされたループを持たないN個の要素のうち、それぞれが2つの供給が制限されたもの

私はリストのリストを持っており、各内側のリストから1つの要素を選択するすべての可能な組み合わせを繰り返したいと思う。コンパイル時にリストがいくつあるのか分かっていればかなり簡単ですが、リストがいくつあるのかを事前に知っていないとどうすればいいですか?

私が3つのリストを持っていれば(私が知っていれば、コンパイル時には3つのリストがあります)、3つのリストのそれぞれから1つの要素を選択するすべての組み合わせが欲しいです。 LINQクエリ:

var list1 = new[] { 1, 2 };
var list2 = new[] { 3, 4 };
var list3 = new[] { 5, 6 };
var combinations = from item1 in list1
                   from item2 in list2
                   from item3 in list3
                   select new[] { item1, item2, item3 };
// Results:
// {1, 3, 5}
// {1, 3, 6}
// {1, 4, 5}
// {1, 4, 6}
// {2, 3, 5}
// {2, 3, 6}
// {2, 4, 5}
// {2, 4, 6}

しかし、コンパイル時にリストがいくつあるのかわからないときに、私は同じことをどうやってやることができますか?

var lists = new[] {
    new[] { 1, 2 },
    new[] { 3, 4 },
    new[] { 5, 6 } };
var combinations = ???;

// This particular example happens to be the same inputs as above, so it
// has the same expected outputs. But there could be two lists instead,
// or four, so the three hard-coded "from" clauses won't work.

これはLINQで実際に実行可能なようです - SelectManyはすでに2つのネストされたforeachループに相当します。か何か。しかし、そのようなメタが始まると、私の脳はすべて結びついてしまいます。私は一緒に作品をまとめる方法を手に入れることはできません。私は外部SelectManyコールのジェネリック型引数がどんなものか分かりません。

どのようにリストのリストを反復し、コンパイル時にリストがいくつあるのか知らずに、すべての組み合わせを返すことができますか?

(Note: everywhere I used arrays above, I'd be fine with using IEnumerable instead. Arrays are easier to write in sample code, but I'm expecting that the output is more likely to be in the form IEnumerable> rather than the int[][] I show in my sample output above.)

5
これは、質問と重複するものではなく、両方の質問で一定数のリストを尋ねていますが、両方の質問には実際に回答(どちらの場合も人の答え!
追加された 著者 Joe White,
@スティーブン、あなたがリンクしている質問は私のものより新しいので、もしあれば、それはこのものの複製です。
追加された 著者 Joe White,
回答があります
追加された 著者 Ufuk Hacıoğulları,

1 答え

SelectManyコールを組み合わせるためにSelectManyを使用しません。集計を使用します。 Eric Lippert のコード礼儀(これよりはるかに具体的な質問に答える1つですが、この質問にも合った一般的な答えを出してください):

static IEnumerable> CartesianProduct(
    this IEnumerable> sequences)
{
    IEnumerable> emptyProduct = new[] { Enumerable.Empty() };
    return sequences.Aggregate(
        emptyProduct,
        (accumulator, sequence) => 
            from accseq in accumulator 
            from item in sequence 
            select accseq.Concat(new[] {item}) :                         
        );
}

すべてのEricの回答と同様に、彼は正確に記述された詳細な議論を含んでいますどのように、なぜこれが動作するのか、それと同等の非LINQコードの観点からです。

2
追加された