Как преобразовать массив ND в 1D и вернуть его обратно - PullRequest
1 голос
/ 23 мая 2019

Мне нужно преобразовать массив 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 ]

1 голос
/ 25 мая 2019
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
1 голос
/ 23 мая 2019

Ну, я решаю это странным образом.Я открыт для лучших подходов

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;
    }
...