3

i 個の項目を持つ IEnumerable があり、それを反復して j 個の項目を持つ別の IEnumerable に対してテストする必要があります。ただし、i はランダムに繰り返され、j のすべての繰り返しで i とは異なる項目がテストされる可能性があります。

list_of_is = [ a, b, c, d, e, f, g ]
list_of_js = [ x, y, z ]

i をランダム化するのは些細なことだと仮定しましょう。

random_is[x] = [ e, b, f, g, d, a, c ]
random_is[y] = [ f, b, g, c, a, d, e ]
random_is[z] = [ d, g, f, c, b, e, a ]

ここで、基本的に必要なものは次のとおりです。

for (int i = 0; i < list_of_is.Count(); i++)
{
   foreach (var j in list_of_js)
   {
      yield return j.DoSomething(random_is[j][i]);
   }
}

出力は次のようになります。

   e x、 f y、 d z、 b x、 b y、 g z、 ...

さて、random_is変数を保存せずにこれを行う方法はありますか? どちらのリストも非常に大きく、大量のメモリを消費します。

編集: 明確にするために、順序は重要です。j の各パスは、random_i の次のアイテムのみを「処理」する必要があります。全体として、処理は次の順序で完了する必要があります。

ここに画像の説明を入力

4

2 に答える 2

1

この問題を回避する1つの方法は、ループを交換することです。あれは:

foreach (var j in list_of_js)
{
    random_i = generateRandom(j);
    for (int i = 0; i < list_of_is.Count(); ++i)
    {
        return j.DoSomething(random_i[i]);
    }
}

コードを見ても、それreturnはループを殺すでしょう。おそらくあなたは意味しましたyield returnか?

いずれの場合も、これにより、各ランダムリストを1回だけ生成する必要がありrandom_is、メモリ内に一度に1つのコレクションのみが必要になります。ただし、生成される順序は変更されます。中間値を保存し、すべての値が生成された後で再配置できれば、それは問題ではありません。

于 2012-10-30T23:09:13.187 に答える
1

列挙子は、定義上、トークンごとに一度に1つの値を取得するため、最初に配列に変換しない限り、Enumerableを実際にランダム化することはできません。

だから、私が正しく理解していれば、私はこのようなことをするでしょう...

  1. list_of_isを配列に変換します
  2. list_of_jsのjごとに
  3. list_of_isをループしてFisher-Yatesシャッフルを実行します
  4. list_of_isをループして、f(j、i)を実行します。ここで、iはシャッフルの現在のインデックスです。

ここに簡単な例があります、これが役立つことを願っています(申し訳ありませんがいくつかのエラーを修正しました)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {

        static IEnumerable<char> list_of_is = new char[] {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
        static IEnumerable<char> list_of_js = new char[] { 'x', 'y', 'z' };

        static void Main(string[] args)
        {
            foreach (string result in Randomize())
                Debug.Write(result);
        }

        public static IEnumerable<String> Randomize()
        {
            char[] random_is = list_of_is.ToArray();
            int jCount = list_of_js.Count();

            Random r = new Random();

            // foreach j
            foreach(char j in list_of_js)
            {
                // create a random ordering of is
                for (int i = random_is.Length - 1; i >= 0; i--)
                {
                    int x = r.Next(0, i);

                    // swap
                    char temp = random_is[x];
                    random_is[x] = random_is[i];
                    random_is[i] = temp;
                }

                // now evaluate the random pairs
                foreach(Char i in random_is)
                    yield return String.Format("{0}{1} ", Char.ToUpper(i), j);
            }
        }
    }
}

出力

Gx Cx Ex Bx Fx Ax Dx Dy By Fy Ay Cy Gy Ey Bz Az Gz Cz Fz Ez Dz

編集: 実際、あなたの擬似コードが完全に正しくないように思われることに気づきました。7つの値の3つのランダム配列を生成し、ランダム配列ごとにX、Y、Zのペアを出力したいとします。その場合、yoouには3 * 7 * 3=63出力が必要になるようです。

したがって、これはより正確である可能性があります。

public static IEnumerable<String> Randomize()
{
    char[] random_is = list_of_is.ToArray();
    int jCount = list_of_js.Count();

    Random r = new Random();

    // foreach j
    for (int random = 0; random < jCount; random++)
    {
        // create a random ordering of is
        for (int i = random_is.Length - 1; i >= 0; i--)
        {
            int x = r.Next(0, i);

            // swap
            char temp = random_is[x];
            random_is[x] = random_is[i];
            random_is[i] = temp;
        }

        // now evaluate the random pairs
        foreach (Char i in random_is)
            foreach(Char j in list_of_js)
                yield return String.Format("{0}{1} ", Char.ToUpper(i), j);
    }
}

そしてそれは出力します:

Cx Cy Cz Gx Gy Gz Dx Dy Dz Bx By Bz Fx Fy Fz Ax Ay Az Ex Ey Ez Bx By Bz Cx Cy Cz Fx Fy Fz Ax Ay Az Ex Ey Ez Dx Dy Dz Gx Gy Gz Cx Cy Cz Ax Ay Az Bx By Bz Gx Gy Gz Fx Fy Fz Ex Ey Ez Dx Dy Dz
于 2012-10-30T23:59:39.197 に答える