使用线性索引在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<int> 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<int> 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<int> getCumulativeLengths(Array arr)
{
List<int> lengths = new List<int>(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<int>)lengths;
}
}
有没有办法更有效地做同样的事情,并且可能使用框架本身提供的东西(即可以毫不费力地使用的东西。)
谢谢,
SDX2000。
答案 0 :(得分:2)
为什么需要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);
}
}
答案 1 :(得分:1)
你知道最初会存在多少元组吗?如果您说的是尺寸为x x x x c x d的矩阵,则无法使用以下内容获取所有索引的列表:
for i=0 to (a*b*c*d)
Array[i % a, (i/a) % b, (i/(a*b) % c, i / (a*b*c)] = 30
因此,当计数器滚过各种边界时,每个后续索引都会增加。如果有更多,这确实推广到n元组只是乘以先前的值。如果想要以不同的方式遍历,可以反转指数的算法。
答案 2 :(得分:0)
SetValue()
应该有效。看看this获得更多灵感。
{{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}
}
作为旁注,您确定要从IList<int>
返回getCumulativeLengths
吗?
我一直认为,输入要慷慨,输出要严格。
答案 3 :(得分:0)
PKG_CPPFLAGS = -I../inst/include/