C# 在单个循环中在多维数组上循环
假设有一个具有2列的多维数组,每列具有完全相同的元素计数: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
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}));
}
}
}