Algorithm to convert a multi-dimensional array to a one-dimensional array

前端 未结 5 1564
挽巷
挽巷 2020-12-06 01:29

It\'s easy enough to convert a 2-dimensional array to a single-dimensional array but how can I convert a multi-dimensional array of more than 2 dimensions to a one-dimension

5条回答
  •  盖世英雄少女心
    2020-12-06 01:35

    You could do the following in C#.

    public class ArrayIndexer
    {
        private readonly int[] _bounds;
        private readonly int[] _sum;
    
        public ArrayIndexer(params int[] bounds)
        {
            _bounds = bounds;
    
            // Pre-compute bounds sums for speed.
            _sum = new int[bounds.Length - 1];
            for (int i = 1, sum = _bounds[i - 1]; i < _bounds.Length; ++i, sum *= _bounds[i - 1])
                _sum[i-1] = sum;
        }
    
        public T Index(T[] array, params int[] indices)
        {
            if (indices.Length != _bounds.Length)
                throw new ArgumentException("There should be as many indices as bounds", "indices");
    
            var index = indices[0];
            for (int i = 1, sum = _bounds[i - 1]; i < indices.Length; ++i, sum *= _bounds[i - 1])
                index += sum * indices[i];
            return array[index];
        }
    
        public T FastIndex(T[] array, params int[] indices)
        {
            if (indices.Length != _bounds.Length)
                throw new ArgumentException("There should be as many indices as bounds", "indices");
    
            var index = indices[0];
            for (int i = 1; i < indices.Length; ++i)
                index += _sum[i-1] * indices[i];
            return array[index];
        }
    }
    

    Or to transform into an n-dimensional array.

    public static class ArrayExtensions
    {
        public static Array CreateArray(this T[] array1d, params int[] bounds)
        {
            var arrayNd = Array.CreateInstance(typeof(T), bounds);
    
            var indices = new int[bounds.Length];
            for (var i = 0; i < array1d.Length; ++i)
            {
                arrayNd.SetValue(array1d[i], indices);
    
                for (int j = 0; j < bounds.Length; ++j)
                {
                    if (++indices[j] < bounds[j])
                        break;
                    indices[j] = 0;
                }
            }
    
            return arrayNd;
        }
    }
    

    And to test.

    int[] array3d =
        new[]
        {
            0, 1, 2, 3,
            4, 5, 6, 7,
            8, 9, 10, 11,
    
            12, 13, 14, 15,
            16, 17, 18, 19,
            20, 21, 22, 23
        };
    
    var copied3d = (int[, ,])array3d.CreateArray(4, 3, 2);
    var indexer3d = new ArrayIndexer(4, 3, 2);
    
    for (int i = 0; i < 4; ++i)
    {
        for (int j = 0; j < 3; ++j)
        {
            for (int k = 0; k < 2; ++k)
            {
                var x = indexer3d.FastIndex(array3d, i, j, k);
                var y = copied3d[i, j, k];
                Debug.Print("Array[{0},{1},{2}] = {3} and {4} match = {5}", i, j, k, x, y, x == y);
            }
        }
    }
    

提交回复
热议问题