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

时间:2008-12-11 16:10:28

标签: 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
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。

4 个答案:

答案 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)

PKG_CPPFLAGS =  -I../inst/include/

答案 3 :(得分: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吗?

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

豫ICP备18024241号-1