Использование push
и автовивификация.
Начните с обычного вопроса:
#! /usr/bin/perl
use warnings;
use strict;
Прочитайте пример ввода из файлового дескриптора DATA
и создайте структуру данных, аналогичную той, которую вы сбросили:
my @hashes;
while (<DATA>) {
my $VAR1;
$VAR1 = eval $_;
die $@ if $@;
push @hashes => $VAR1;
}
Ваш ввод имеет два случая:
- Ссылка на массив, содержащий данные, которые должны быть объединены с его двоюродными братьями, имеющими тот же «ключевой путь».
- В противном случае это ссылка на хеш, который содержит ссылку на массив из случая 1 на некоторой глубине, поэтому мы удаляем самый внешний слой и продолжаем копать.
Обратите внимание на использование $_[0]
. Семантика подпрограмм Perl такова, что значения в @_
являются псевдонимами , а не копиями. Это позволяет нам вызывать merge
напрямую, без необходимости сначала создавать связку лесов для хранения объединенного содержимого. Код перестанет работать, если вы скопируете значение.
sub merge {
my $data = shift;
if (ref($data) eq "ARRAY") {
push @{ $_[0] } => @$data;
}
else {
foreach my $k (%$data) {
merge($data->{$k} => $_[0]{$k});
}
}
}
Теперь мы идем @hashes
и постепенно объединяем их содержимое в %merged
.
my %merged;
foreach my $h (@hashes) {
foreach my $k (keys %$h) {
merge $h->{$k} => $merged{$k};
}
}
Мы не знаем, в каком порядке поступили значения, поэтому запустите последний этап очистки, чтобы отсортировать массивы:
sub sort_arrays {
my($root) = @_;
if (ref($root) eq "ARRAY") {
@$root = sort { $a <=> $b } @$root;
}
else {
sort_arrays($root->{$_}) for keys %$root;
}
}
sort_arrays \%merged;
Модуль Data :: Dumper отлично подходит для быстрой отладки!
use Data::Dumper;
$Data::Dumper::Indent = 1;
print Dumper \%merged;
Поместите копию ввода вашего вопроса в специальный DATA
дескриптор файла:
__DATA__
$VAR1 = { '999' => { '998' => [ '908', '906', '0', '998', '907' ] } };
$VAR1 = { '999' => { '991' => [ '913', '920', '918', '998', '916', '919', '917', '915', '912', '914' ] } };
$VAR1 = { '999' => { '996' => [] } };
$VAR1 = { '999' => { '995' => [] } };
$VAR1 = { '999' => { '994' => [] } };
$VAR1 = { '999' => { '993' => [] } };
$VAR1 = { '999' => { '997' => [ '986', '987', '990', '984', '989', '988' ] } };
$VAR1 = { '995' => { '101' => [] } };
$VAR1 = { '995' => { '102' => [] } };
$VAR1 = { '995' => { '103' => [] } };
$VAR1 = { '995' => { '104' => [] } };
$VAR1 = { '995' => { '105' => [] } };
$VAR1 = { '995' => { '106' => [] } };
$VAR1 = { '995' => { '107' => [] } };
$VAR1 = { '994' => { '910' => [] } };
$VAR1 = { '993' => { '909' => [] } };
$VAR1 = { '993' => { '904' => [] } };
$VAR1 = { '994' => { '985' => [] } };
$VAR1 = { '994' => { '983' => [] } };
$VAR1 = { '993' => { '902' => [] } };
$VAR1 = { '999' => { '992' => [ '905' ] } };
Пример выходных данных ниже:
'994' => {
'910' => [],
'985' => [],
'983' => []
},
'999' => {
'993' => [],
'992' => [
'905'
],
'997' => [
'984',
'986',
'987',
'988',
'989',
'990'
],