6

たとえば、リストが2つある場合は、次のようにします。

foreach (Item item1 in lists[0])
  foreach (Item item2 in lists[1])
    // Do something with item1 and item2

または私が3つ持っていたら、私はします

foreach (Item item1 in lists[0])
  foreach (Item item2 in lists[1])
    foreach (Item item3 in lists[2])
      // Do something with item1, item2, and item3

しかし、コンパイル時にコレクションに含まれるリストの数がわからない場合、listsすべての順列を簡単に繰り返すにはどうすればよいですか?

AC#ソリューションが理想的ですが、適切なアルゴリズムを示す任意の言語のソリューションが便利です。

良い2次元の例は、スプレッドシートの列のリストと行のリストで、各セルで処理を行う必要があります。ただし、これはn次元の問題です。

4

3 に答える 3

5

EricLippertによるこのテーマに関する素晴らしい記事があります。

結果に到達するためのプロセスを説明しているので、この記事を読むことを強くお勧めしますが、最終的には、結果のコードは短くて甘いものです。

(リンクから逐語的にコピー)

static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences) 
{ 
  IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() }; 
  return sequences.Aggregate( 
    emptyProduct, 
    (accumulator, sequence) => 
      from accseq in accumulator 
      from item in sequence 
      select accseq.Concat(new[] {item})); 
}
于 2012-10-10T16:50:42.277 に答える
1
    public static IEnumerable<T[]> IterateOverLists<T>(this IList<IEnumerable<T>> lists )
    {
        var array = new T[lists.Count];
        return IterateOverLists( lists, array, 0 );
    }
    private static IEnumerable<T[]> IterateOverLists<T>(this IList<IEnumerable<T>> lists, T[] array, int index)
    {
        foreach (var value in lists[index])
        {
            array[index] = value;
            if (index == lists.Count - 1)
            {
                // can make a copy of the array here too...
                yield return array;
            }
            else
            {
                foreach (var item in IterateOverLists(lists, array, index + 1))
                {
                    yield return item;
                }
            }
        }
    }

リストの1つが空の場合、それはすべてを殺しますが、それを回避できるはずです...

于 2012-10-10T16:45:20.380 に答える
0
for (int i = 0; i < lists.Length; i++) {
    foreach (Item item in lists[i]) {
       ....
    }
}
于 2012-10-10T16:33:51.130 に答える