Как я могу программно преобразовать список массивов, подобных этому
$dat_a = [qw( a1 b1 c1 d1 e1)]
$dat_b = [qw( a1 b1 c2 d2 e1)]
$dat_c = [qw( a1 b2 c3)]
[...]
в иерархию (хэш), например
# {a1}--{b1}-{c1}-{d1}{e1}=42
# \ \{c2}-{d2}{e1}=84
# |{b2}-{c3}=72
Заполнение хеша таким образом динамически генерируемым кодом:
$dat_hierarchy->{a1}{b1}{c1}{d1}{e1} ++
$dat_hierarchy->{a1}{b1}{c2}{d2}{e1} ++
$dat_hierarchy->{a1}{b2}{c3} ++
Моя проблема в том, что массивы внутри трассы имеют разные
длина и максимальная длина также варьируется между прогонами.
Аналогичная проблема заключалась бы в преобразовании путей к файлам в деревья каталогов,
поэтому я полагаю, что были бы некоторые стандартные алгоритмы для решения
это проблемы.
Если я жестко закодирую глубину (или длину массива), возможное решение, которое я
можно подумать, чтобы преобразовать эту проблему в более общую
преобразование матрицы в иерархию. Это подразумевает преобразование массивов
в матрицу (добавляя конечные 0, чтобы все массивы с одинаковыми
длина). Таким образом, решение будет тривиальным (если сценарий
жестко закодировано для глубины / длины)
#[Perlish pseudocode]
$max_array_idx = find_maximum_array_index (\@list_of_arrays)
@lst_of_matrix_arrays = fill_to_same_length(\@list_of_arrays, $max_array_idx)
$hierarchy = create_tree(\@list_of_matrix_arrays, $max_array_idx)
sub create_tree {
my ($list_of_matrix_arrays, $max_array_idx) = @_;
# <problem> how to dinamically handle $max_array_idx??
# if I use fixed depth then is trivial
# $max_fixed_idx = 2
# hardcoded hash construction for depth 3!
# Trivial solution for fixed hash depth:
foreach my $array ($list_of_matrix_arrays) {
$dat_hierarchy->{$array->[0]}{$array->[1]}{$array->[2]} ++
}
}
Итак, я буду признателен за любые предложения о том, как избежать жесткого кодирования
максимальное количество индекса массива, используемого при создании хэша,
Возможным решением может быть использование некоторого метапрограммирования для заполнения хеша с использованием среды выполнения $ max_fixed_idx ?.
это будет что-то вроде следующей хорошей идеи?
sub populate_hash {
my ($array) = @_;
my $array_max_idx = @$array - 1;
# create hash_string " $dat_hierarchy->{$array->[0]}{$array->[1]}{$array->[2]} ++"
my $str = '$dat_hierarchy->';
foreach my $idx (0..$array_max_idx) {
# using the indexes instead the elements to avoid quotation problems
$str .= '{$array->['.$idx.']}';
# how to sanitize the array element to avoid code injection in the further eval? what happen if an array element is called "sub {system('rm -rf ~/')}" ;-)
# http://xkcd.com/327/
}
$str .= ' ++';
# populate hash
# $str for lengh 3 arrays would be '$dat_hierarchy->{$array->[0]}{$array->[1]}{$array->[2]} ++'
eval($str) or die 'error creating the hash';
}
А как насчет рекурсии?