如何使用线性索引在多维数组中设置值

使用线性索引在C#多维数组中设置值的最有效方法是什么? 例如给定一个数组……

int[,,] arr2 = { {{0,1,2}, {3,4,5}, {6,7,8}} , {{9,10,11}, {12,13,14}, {15,16,17}} , {{18,19,20}, {21,22,23}, {24,25,26}} }; 

如何使用线性索引将所有元素设置为30 …

 //This code does not work for (int i = 0; i < arr.Length; i++) { arr.SetValue(30, i); } 

显然上面的SetValue()不适用于多维数组。

这是我能想到的最佳解决方案……

编辑:为代码添加了一些说明……

 static class Program { static void Main(string[] args) { //Sample input. int[,,] arr2 = { {{0,1,2}, {3,4,5}, {6,7,8}} , {{9,10,11}, {12,13,14}, {15,16,17}} , {{18,19,20}, {21,22,23}, {24,25,26}} }; int[] arr1 = { 1, 2, 3, 4 }; setElementsTo30(arr2); setElementsTo30(arr1); } //Must be able to process int arrays of arbitrary dimensions and content private static void setElementsTo30(Array arr) { IList cumulativeLength = getCumulativeLengths(arr); for (int i = 0; i < arr.Length; i++) { SetValue(arr, i, 30, cumulativeLength); } } public static void SetValue(this Array arr, int index, object value, IList cumulativeLength) { int[] arrayIndex = new int[arr.Rank]; for (int dim = arr.Rank-1; dim >= 0; dim--) { arrayIndex[dim] = index / cumulativeLength[dim] % arr.GetLength(dim); } arr.SetValue(value, arrayIndex); } private static IList getCumulativeLengths(Array arr) { List lengths = new List(arr.Rank); for (int dim = 0; dim < arr.Rank; dim++) { int prod = 1; for (int i = dim + 1; i < arr.Rank; i++) { prod *= arr.GetLength(i); } lengths.Add(prod); } return (IList)lengths; } } 

有没有办法更有效地做同样的事情,并可能使用框架本身提供的东西(即可以毫不费力地使用的东西。)

谢谢,
SDX2000。

为什么你需要IList?

 static void SetValue2(this Array a, object value, int i) { int[] indices = new int[a.Rank]; for (int d = a.Rank - 1; d >= 0; d--) { var l = a.GetLength(d); indices[d] = i % l; i /= l } a.SetValue(value, indices); } 

测试代码:

 static void Main(string[] args) { int[, ,] arr2 = { {{0,1,2}, {3,4,5}, {6,7,8}}, {{9,10,11}, {12,13,14}, {15,16,17}}, {{18,19,20}, {21,22,23}, {24,25,26}} }; for (int i = 0; i < arr2.Length; i++) { arr2.SetValue2(30, i); } } 

你知道最初会存在多少个元组吗? 如果您说维度为axbxcxd的矩阵,则无法使用以下内容获取所有索引的列表:

 for i=0 to (a*b*c*d) Array[i % a, (i/a) % b, (i/(a*b) % c, i / (a*b*c)] = 30 

因此,当计数器滚过各种边界时,每个后续索引都会增加。 如果有更多,这确实推广到n元组只是乘以先前的值。 如果想要以不同的方式遍历,则可以反转索引的算法。

SetValue()应该工作。 看看这个以获得更多灵感。

编辑:你能做到吗?

 {{30,30,30}, {30,30,30}, {30,30,30}} , {{30,30,30}, {30,30,30}, {30,30,30}} , {{30,30,30}, {30,30,30}, {30,30,30} } 

作为旁注,您确定要从getCumulativeLengths返回IList吗?

我一直认为,输入要慷慨,输出要严格。

  public static void CopyToMultidimensionalArray(this IList source, Array target, IList dimensions) { var indices = new int[dimensions.Count]; for (var i = 0; i < source.Count; i++) { var t = i; for (var j = indices.Length - 1; j >= 0; j--) { indices[j] = t % dimensions[j]; t /= dimensions[j]; } target.SetValue(source[i], indices); } }