C# 在单个循环中在多维数组上循环

C# 在单个循环中在多维数组上循环,c#,arrays,multidimensional-array,C#,Arrays,Multidimensional Array,假设有一个具有2列的多维数组,每列具有完全相同的元素计数: int[,] virtualArray = new int[800,2]; 如果我在一个循环中对这样的数组进行迭代,我会执行如下操作: int columnCount = 2; int eachColumnElementCount = 800; int totalCombinationCount = Convert.ToInt32(Math.Pow(eachColumnElementCount, columnCount)); // 6

假设有一个具有2列的多维数组,每列具有完全相同的元素计数:

int[,] virtualArray = new int[800,2];
如果我在一个循环中对这样的数组进行迭代,我会执行如下操作:

int columnCount = 2;
int eachColumnElementCount = 800;
int totalCombinationCount = Convert.ToInt32(Math.Pow(eachColumnElementCount, columnCount)); // 640_000

for(int i = 0; i < totalCombinationCount ; i++) {
        int columnOneIndex= index / totalCombinationCount ;
        int columnTwoIndex= index - totalCombinationCount * eachColumnElementCount;
}
结果将是:

0,0 i=0

0,1

0799 i=799

1,0 i=800

1,1

1799年

799799 i=640_000-1

现在,我想扩展我当前的实现,在一个单维循环中迭代-在一个包含3列的多维数组上!即,假设我们在每列中有相同的800元素计数,预期结果如下:

int[,] virtualArray = new int[800,3];

int columnCount = 3;
int eachColumnElementCount = 800;
int totalCombinationCount = Convert.ToInt32(Math.Pow(eachColumnElementCount, columnCount)); // 512_000_000

for(int i = 0; i < totalCombinationCount ; i++) {
        // int index1 = 0; // ??
        // int index2 = 0; // ??
        // int index3 = 0; // ??
}
0,0,0 i=0

0,0,1

0,0799

1080156

799799799 i=512_000_000-1


如果有3列,我想不出一个公式。。有没有一种方法可以在单个循环中循环此类数组?

当然可以,请尝试以下Java代码:

int columnCount = 3;
        int eachColumnElementCount = 800;
        int totalCombinationCount = (int)Math.pow(eachColumnElementCount, columnCount); // 800*800*800

        for(int i = 0; i < totalCombinationCount ; i++) {
                int column1Index= i % eachColumnElementCount;
                int column2Index= i / eachColumnElementCount % eachColumnElementCount ;
                int column3Index= i / eachColumnElementCount / eachColumnElementCount ;
                System.out.println(column3Index+","+column2Index+","+column1Index);
        }

我知道您问过如何对三列执行此操作,但如果您想将其推广到N列,则会有点麻烦

你所计算的就是所谓的a

埃里克·利珀特

看起来是这样的:

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}));
}
请注意,您不需要为不同的列数编写不同的代码-这适用于任何大于1的列数

将整个过程整合到一个简单的控制台应用程序中:

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

namespace Demo
{
    static class Program
    {
        static void Main()
        {
            char[,] array =
            {
                { 'A', 'F', 'K', 'P' },
                { 'B', 'G', 'L', 'Q' },
                { 'C', 'H', 'M', 'R' },
                { 'D', 'I', 'N', 'S' },
                { 'E', 'J', 'O', 'T' },
            };

            foreach (var combination in CartesianProduct(ByColumn(array)))
                Console.WriteLine(string.Concat(combination));
        }

        public static IEnumerable<T> Column<T>(T[,] array, int column)
        {
            for (int row = array.GetLowerBound(0); row <= array.GetUpperBound(0); ++row)
                yield return array[row, column];
        }

        public static IEnumerable<IEnumerable<T>> ByColumn<T>(T[,] array)
        {
            for (int column = array.GetLowerBound(1); column <= array.GetUpperBound(1); ++column)
                yield return Column(array, column);
        }

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

我不明白为什么要对同一个元素迭代这么多次。只有2*800=1600个元素,但要迭代640000次。因此,您需要多次访问每个元素。您需要第二次循环…因为您需要通过columns@MatthewWatson这是个好问题。我的最终目标是迭代所有可能的值组合。仅仅从数组中获取必要的元素是不够的。正如你所说的——总共只有1600个元素,但这1600个元素可以创建640000个独特的组合。啊,所以你想要的是每列中一个元素的每个组合。这就是我喜欢Java的地方。语法与C非常相似!我计划使用CUDA执行循环,因此我将稍微修改C/C++的代码。你的解决方案非常有效!非常感谢。
char[,] array =
{
    { 'A', 'F', 'K', 'P' },
    { 'B', 'G', 'L', 'Q' },
    { 'C', 'H', 'M', 'R' },
    { 'D', 'I', 'N', 'S' },
    { 'E', 'J', 'O', 'T' },
};

foreach (var combination in CartesianProduct(ByColumn(array)))
    Console.WriteLine(string.Concat(combination));
using System;
using System.Collections.Generic;
using System.Linq;

namespace Demo
{
    static class Program
    {
        static void Main()
        {
            char[,] array =
            {
                { 'A', 'F', 'K', 'P' },
                { 'B', 'G', 'L', 'Q' },
                { 'C', 'H', 'M', 'R' },
                { 'D', 'I', 'N', 'S' },
                { 'E', 'J', 'O', 'T' },
            };

            foreach (var combination in CartesianProduct(ByColumn(array)))
                Console.WriteLine(string.Concat(combination));
        }

        public static IEnumerable<T> Column<T>(T[,] array, int column)
        {
            for (int row = array.GetLowerBound(0); row <= array.GetUpperBound(0); ++row)
                yield return array[row, column];
        }

        public static IEnumerable<IEnumerable<T>> ByColumn<T>(T[,] array)
        {
            for (int column = array.GetLowerBound(1); column <= array.GetUpperBound(1); ++column)
                yield return Column(array, column);
        }

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