如何将ND数组转换为一维并将其还原回

时间:2019-05-23 10:13:05

标签: c# arrays multidimensional-array

我需要将n数组(维数未知)转换为1d并将其还原回nd数组。

我遍历整个数组并将元素添加到1d进行转换,但是我不知道如何将其还原。

public class ArrayND<T>
{
    private int[] _lengths;

    private Array _array;

    public ArrayND(int[] length)
    {
        _lengths = length;
        _array = Array.CreateInstance(typeof (T), _lengths);
    }
}


///Loop through 
public float[] ConvertTo1D(ArrayND<float> ndArray)
{
    float[] OneDArray = new float[ndArray.Values.Length];

    System.Collections.IEnumerator myEnumerator = ndArray.Values.GetEnumerator();

    int cols = ndArray.Values.GetLength(ndArray.Values.Rank - 1);
    int j = 0;
    while (myEnumerator.MoveNext())
    {
        OneDArray[j] = (float)myEnumerator.Current;
        j++;
    }

    return OneDArray;
}

2 个答案:

答案 0 :(得分:1)

好吧,我以一种奇怪的方式解决了它。我愿意采用更好的方法

public ArrayND<string> convert1DtoND(string[] oneDarray, int[] dimension)
    {

        ArrayND<string> ndArray = new ArrayND<string>(dimension);

        int[] index = new int[ndArray.Values.Rank];
        int[] length = new int[ndArray.Values.Rank];
        int j = 0;

        for (int i = 0; i < length.Length; i++)
        {
            length[i] = ndArray.Values.GetLength(i);
        }
        do
        {
            ndArray[index] = oneDarray[j];
            j++;
        } while (Increment(index, length));

        return ndArray;

    }
 public static bool Increment(int[] index, int[] length)
    {
        int i = index.Length - 1;
        index[i]++;
        while (i >= 0 && index[i] == length[i] && length[i] > 0)
        {
            index[i--] = 0;
            if (i >= 0)
                index[i]++;
        }
        if (i < 0 || length[i] == 0)
            return false;
        else
            return true;
    }

答案 1 :(得分:1)

public class ArrayND<T>
{
    private int[] _lengths;

    private Array _array;

    public ArrayND(int[] length)
    {
        _lengths = length;
        _array = Array.CreateInstance(typeof(T), _lengths);
    }

    public T GetValue(int[] index) => (T)_array.GetValue(index);

    public void SetValue(T value, int[] index) => _array.SetValue(value, index);

    public T[] ToOneD() => _array.Cast<T>().ToArray();

    public static ArrayND<T> FromOneD(T[] array, int[] lengths)
    {
        if (array.Length != lengths.Aggregate((i, j) => i * j))
            throw new ArgumentException("Number of elements in source and destination arrays does not match.");

        var factors = lengths.Select((item, index) => lengths.Skip(index).Aggregate((i, j) => i * j)).ToArray();
        var factorsHelper = factors.Zip(factors.Skip(1).Append(1), (Current, Next) => new { Current, Next }).ToArray();

        var res = new ArrayND<T>(lengths);
        for (var i = 0; i < array.Length; i++)
            res.SetValue(array[i],
                         factorsHelper.Select(item => i % item.Current / item.Next).ToArray());

        return res;
    }

    public override bool Equals(object obj) =>
        (obj is ArrayND<T> ndArray) &&
        _lengths.SequenceEqual(ndArray._lengths) &&
        _array.Cast<T>().SequenceEqual(ndArray._array.Cast<T>());

    public override int GetHashCode() =>
        new[] { 17 }
        .Concat(_lengths.Select(i => i.GetHashCode()))
        .Concat(_array.Cast<T>().Select(i => i.GetHashCode()))
        .Aggregate((i, j) => unchecked(23 * i + j));
}

它可用于任何尺寸。

测试:

int I = 2, J = 3, K = 4;
var a = new ArrayND<int>(new[] { I, J, K });
var v = 0;
for (var i = 0; i < I; i++)
    for (var j = 0; j < J; j++)
        for (var k = 0; k < K; k++)
            a.SetValue(++v, new[] { i, j, k });

var b = a.ToOneD();
var c = ArrayND<int>.FromOneD(b, new[] { I, J, K });
Console.WriteLine(a.Equals(c)); // True

或:

int I = 2, J = 3;
var a = new ArrayND<int>(new[] { I, J });
var v = 0;
for (var i = 0; i < I; i++)
    for (var j = 0; j < J; j++)
        a.SetValue(++v, new[] { i, j });

var b = a.ToOneD();
var c = ArrayND<int>.FromOneD(b, new[] { I, J });
Console.WriteLine(a.Equals(c)); // True

或:

int I = 2, J = 3, K = 4, M = 5;
var a = new ArrayND<int>(new[] { I, J, K, M });
var v = 0;
for (var i = 0; i < I; i++)
    for (var j = 0; j < J; j++)
        for (var k = 0; k < K; k++)
            for (var m = 0; m < M; m++)
                a.SetValue(++v, new[] { i, j, k, m });

var b = a.ToOneD();
var c = ArrayND<int>.FromOneD(b, new[] { I, J, K, M });
Console.WriteLine(a.Equals(c)); // True