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

C# 如何使用线性索引在多维数组中设置值,c#,.net,C#,.net,使用线性索引在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

使用线性索引在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);
}
//此代码不起作用
对于(int i=0;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;
    }
}
静态类程序
{
静态void Main(字符串[]参数)
{
//样本输入。
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};
将元件设置为30(arr2);
将元件设置为30(arr1);
}
//必须能够处理任意维度和内容的int数组
私有静态void setElementsTo30(数组arr)
{
IList cumulativeLength=GetCumulativeLength(arr);
对于(int i=0;i=0;dim--)
{
arrayIndex[dim]=索引/累积长度[dim]%arr.GetLength(dim);
}
arr.SetValue(值,arrayIndex);
}
专用静态IList GetCumulativeLength(阵列arr)
{
列表长度=新列表(arr.Rank);
对于(整型尺寸=0;尺寸<排列顺序;尺寸++)
{
int prod=1;
对于(int i=dim+1;i
是否有一种方法可以更有效地完成同样的工作,并且可能使用框架本身提供的东西(即可以不费吹灰之力地使用的东西)

谢谢,
SDX2000。

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}

}
作为旁注,是否确实要从
GetCumulativeLength
返回
IList


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

你知道最初会存在多少元组吗?如果你说一个矩阵的维数是a x b 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元组,只需乘以前面的值即可。如果想要以不同的方式进行遍历,可以反转索引的算法。

为什么需要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);
    }
}
static void Main(字符串[]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
公共静态无效复制多维数组(此ILST源、数组目标、ILST维度)
{
var指数=新整数[dimensions.Count];
对于(var i=0;i=0;j--)
{
指数[j]=t%维度[j];
t/=尺寸[j];
}
目标设定值(源[i],索引);
}
}

1。是的,我只限于矩形阵列2。不返回IList是一个仓促的决定。在专业编程过程中,我会返回一个只读集合。3.我的moto-对输入和输出都要严格。如果我还记得的话,我可能会提供一些参考资料:(嗯……我现在意识到我的回答有点仓促。我不完全确定你能以线性方式设置所有内容。你可能必须转到嵌套的for循环。我会继续阅读。@EDIT-实际上这只是一个演示程序,我没有关于输入数组的先验信息(我的代码将用作一个库)。@JB数组可以有任意数量的维度。好的,我终于明白了这一点,我不得不说你做得很好。谢谢你的帮助。我的第一个版本有一个内部for循环,它计算了较低维度的累积大小。我将这些总计保存到一个列表中,以提高(时间)效率。
    public static void CopyToMultidimensionalArray(this IList<object> source, Array target, IList<int> 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);
        }
    }