Присвоить значения одномерного массива многомерному массиву неизвестных размеров / типа - PullRequest
0 голосов
/ 30 июня 2019

У меня есть N-мерный массив, которому я хочу иметь возможность назначить любое примитивное значение. (один тип для одного массива, но alg должен быть универсальным для всех примитивных типов).

Я написал метод, который может сделать это:

var element = Array.CreateInstance(dataType, dataDims);

foreach (var index in GetIndexes(dataDims))
{
     element.SetValue(SomeKindOfValue, index);
}

Функция GetIndexes генерирует все возможные индексы для заданных измерений:

     public static IEnumerable<int[]> GetIndexes(int[] dims)
     {
        int lastIndex = dims.Length - 1;
        int lastDim = dims[lastIndex];
        int[] Index = new int[dims.Length];
        int currentDim = lastIndex;

        while (currentDim >= 0) 
        {
            if (currentDim == lastIndex)
            {
                for (int i = 0; i < lastDim; i++)
                {
                    yield return Index;
                    Index[currentDim]++;
                }

                Index[currentDim] = 0;
                currentDim--;
                continue;
            }
            else
            {
                if (Index[currentDim] == dims[currentDim] - 1)
                {
                    Index[currentDim] = 0;
                    currentDim--;
                    continue;
                }
                else
                {
                    Index[currentDim]++;
                    currentDim = lastIndex;
                    continue;
                }
            }
        }
    }

ПРИМЕР: для GetIndexes (new int [] {4,2,3}) вывод будет:

0, 0, 0 |
0, 0, 1 |
0, 0, 2 | 
0, 1, 0 | 
0, 1, 1 |
0, 1, 2 | 
1, 0, 0 | 
1, 0, 1 | 
1, 0, 2 | 
1, 1, 0 | 
1, 1, 1 | 
1, 1, 2 | 
2, 0, 0 | 
2, 0, 1 | 
2, 0, 2 | 
2, 1, 0 | 
2, 1, 1 | 
2, 1, 2 | 
3, 0, 0 | 
3, 0, 1 | 
3, 0, 2 | 
3, 1, 0 | 
3, 1, 1 | 
3, 1, 2 |

Проблема в том, что присвоение значений таким способом является дорогостоящим, и этот алгоритм должен быть максимально эффективным.

Я думал, что многомерный массив на самом деле является 1d-массивом в памяти, поэтому, если бы я мог получить доступ к указателю каждого элемента, я мог бы присвоить значения без каких-либо вычислений и напрямую. Проблема в том, что мне не удалось найти способ создать указатель на универсальный класс Array (или на его первый элемент).

По сути, я пытаюсь написать общую функцию этого (которая примет любой тип примитива как тип данных массива и примет любой многомерный массив):

public static unsafe void SetElementsByPointer(int[,] array, int[] values)
{
            if (values.Length != array.LongLength)
                 throw new Exception("array and values length mismatch.");

            fixed (int* pStart = array)
            {
                for (int i = 0; i < array.LongLength; i++)
                {
                    int* pElement = pStart + i;
                    *pElement = values[i];
                }
            }
        }

Я буду признателен за любые другие идеи для установки значений в n-мерный массив, но путь указателя кажется наиболее эффективным, просто я не могу понять это

Заранее спасибо.

1 Ответ

0 голосов
/ 30 июня 2019

Чтобы скопировать материал, вы можете использовать это: https://dotnetfiddle.net/vTzJv4

// 1D array
int[] values = new int[] {
    1, 2, 3,
    4, 5, 6
};
// 2D array
int[,] marr = new int[2,3];

// Copy here
System.Buffer.BlockCopy((Array)values, 0, (Array)marr, 0, (int)marr.LongLength * sizeof(int));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...