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

解决这个问题的一种方法是交换你的循环。那是:

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

无论如何,这使得每个随机列表只需要生成一次,并且您一次只需要random_is在内存中收集一个集合。然而,它确实改变了事物的生成顺序。如果您可以保存中间值并在生成所有值后重新排列,那不是问题。

于 2012-10-30T23:09:13.187 回答
1

除非您首先将 Enumerable 转换为数组,否则您无法真正随机化它,因为根据定义,枚举数一次获得 1 个值,一个令牌一个令牌。

所以,如果我理解正确,我会做这样的事情......

  1. 将 list_of_is 转换为数组
  2. 对于 list_of_js 中的每个 j
  3. 循环通过 list_of_is 执行 Fisher-Yates shuffle
  4. 遍历 list_of_is 并执行 f(j,i) 其中 i 是 shuffle 中的当前索引

这是一个简单的例子,我希望这会有所帮助(抱歉修复了一些错误)

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

编辑: 实际上,我只是觉得你的伪代码看起来不太正确。您正在生成 3 个包含 7 个值的随机数组。然后想要为每个随机数组输出 X、Y、Z 对。看来你需要 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 回答