Требуется структура для таблицы измерений "N". Я сомневаюсь, что есть модуль CPAN, который может сделать это, потому что это не такая распространенная ситуация.
Проблема в том, что структура данных растет довольно быстро, а также и в сложности.
Вы можете сохранить N-мерную таблицу в одном списке, используя немного математики для преобразования N-мерного массива в одно измерение. Допустим, X представляет измерение X, а X 'представляет длину этого измерения. Для двумерной таблицы вы можете получить значение, выполнив:
X * Y` + Y.
Для трехмерной таблицы X, Y, Z ответом будет:
X * (Y' * Z') + Y * Z' + Z
Для четырехмерной таблицы W, X, Y, Z ответом будет:
W * (X' * Y' * Z') + X * (Y' + Z') + Y * Z' + Z'
(надеюсь, математика верна).
Поэтому я могу представить такую структуру для N-мерной таблицы. Он будет включать два разных класса: один представляет информацию о размерах, а другой представляет фактические данные (включая все измерения).
- Размер (класс)
- Заголовок (буквенно-цифровая строка)
- Размер измерения (целое число)
- N-таблица (класс)
- Массив измерений (объекты класса измерений)
- Массив данных (буквенно-цифровые строки)
Вы можете получить количество измерений, посмотрев на:
my $numOfDimensions = scalar @{$ntable->{DIMENSIONS}};
И вы можете получить заголовок измерения $x
, посмотрев на:
my xDimensionHeading = $ntable->{DIMENSION}->[$x]->{HEADING};
И, размер этого измерения, глядя на:
my xDimensionSize = $ntable->{DIMENSION}->[$x]->{SIZE};
Конечно, вы бы делали это с настоящими объектно-ориентированными вызовами, а не с голыми ссылками, но это дает вам представление о том, как будет работать структура.
Теперь вам нужен способ преобразования списка целых чисел, который представлял бы местоположение ячейки, в местоположение ячейки вдоль одномерного массива, и у вас будет возможность получать и извлекать ваши данные.
Это то, что вы ищете?
EDIT
Близко к этому, но я на самом деле очень сильно изменяю размеры таблицы (я не могу определить их размер заранее), и, если я понял, ваше решение не подходит для этого.
Это добавляет много сложностей ...
Нам нужно выбросить Size в классе Dimension. И мы не можем использовать одномерный массив для хранения наших данных.
Надеюсь, вы не измените размерность таблицы.
Мы могли бы сделать что-то вроде этого:
- N-таблица (класс)
- Список заголовков измерений {DIMENSION} -> []
- Список данных {DATA} -> [] (это может быть ссылка на другие списки)
Список {DATA} представляет собой ссылку на списки в зависимости от глубины таблицы. Например:
my data_3D = $table_3D->{DATA}->[$x]->[$y]->[$z];
my data_2D = $table_2D->{DATA}->[$x]->[$y];
Количество измерений scalar @{$table->{DIMENSION}}
.
Вопрос в том, как мне получить доступ к данным таким образом, чтобы он не зависел от размеров. Мне может потребоваться 2, 3, 4 или более измерений, и мне нужно как-то структурировать свой адрес, чтобы вытащить его.
У нас мог бы быть какой-то механизм зацикливания. Мы получаем список координат в @coordinates
, а затем смотрим на каждую координату. Последнее будет указывать на данные. Остальное просто будет другой ссылкой на другой массив.
my $data = pop @coordinates; #First Coordinate
$data = $table->[$data]; #Could be data if 1D table, could be a reference
foreach my $coordinate (@coordinates) {
die qq(Not enough coordinates) if ref $data ne 'ARRAY';
$data = $data->[$coordinate]; #Could be data, could be a reference
}
# Cell value is in $data
Также возможно составить список координат, а затем оценить его. Опять полностью не проверено:
$coordinates = "[" . join ("]->[" => @coordinates . "]";
Если бы было три координаты, это было бы
$coordinates = "[$x]->[$y]->[$z]";
Я не уверен, как будет работать одномерный массив ...
Оттуда вы можете построить оператор и использовать eval
для получения данных.
Вам нужно будет использовать несколько методов.
- Установить размеры
- Установите ячейку
- Получить ячейку
- Проверка таблицы полна (я понятия не имею, как это будет работать.
Это скорее мозговая утечка, но я думаю, что это может сработать. У вас нет заданных размеров таблицы, и это может работать для любой N-мерной таблицы.