Как насчет преобразования Шварца ?
#! /usr/bin/perl
use 5.10.0; # for // (aka defined-or)
use warnings;
use strict;
my %data = ...;
# get all subkeys used in %data
my @subkeys = keys %{
{ map { map +($_ => 1),
keys %{ $data{$_} } }
keys %data
}
};
print map qq|$_->[0]: $_->[1] is "$_->[2]"\n|,
sort { $a->[0] cmp $b->[0]
||
$a->[1] cmp $b->[1] }
map { my $key = $_;
map [ $key, $_, $data{$key}{$_} // "" ] =>
@subkeys }
keys %data;
Не забудьте прочитать преобразования Шварцяна сзади-вперед. Первый - ближайший к концу - map
сглаживает или «денормализует» %data
в список записей в некотором неопределенном порядке. Вложенные map
необходимы для доступа к подразделам. Для обработки сколь угодно глубокой вложенности определите рекурсивно flatten
.
Мы сделали более раннюю передачу, чтобы собрать все используемые подключи, поэтому, если конкретный подраздел отсутствует, значение $data{$key}{$_}
является неопределенным значением. Используя //
, определенный или новый оператор, новый в версии 5.10.0, задается значение по умолчанию ""
.
со сплюснутыми записями вида
[ "KEY1", "SUBKEY3", "75.00" ],
[ "KEY1", "SUBKEY1", "Canada" ],
...
сортировка проста: сравните соответствующие первые элементы (ключи) и, если они равны, вернитесь к секундам (подразделы).
Наконец, самый внешний map
форматирует теперь отсортированные денормализованные записи для вывода, и результирующий список отправляется на стандартный вывод с помощью оператора print
.
Выход:
KEY1: SUBKEY1 is "Canada"
KEY1: SUBKEY2 is "50.00"
KEY1: SUBKEY3 is "75.00"
KEY2: SUBKEY1 is "Mexico"
KEY2: SUBKEY2 is ""
KEY2: SUBKEY3 is "200.00"
KEY3: SUBKEY1 is ""
KEY3: SUBKEY2 is "150.00"
KEY3: SUBKEY3 is ""
Чтобы сгруппировать подключи в одной строке с соответствующим ключом каждого, используйте код, например
my @subkeys = sort keys %{ ... ;
foreach my $key (sort keys %data) {
my @values;
foreach my $subkey (@subkeys) {
my $value = $data{$key}{$subkey} // "";
push @values => qq|$subkey is "$value"|;
}
local $" = ", ";
print "$key: @values\n";
}
Вы можете написать это в функциональном стиле, но в результате получается грязный беспорядок:
print map { my $key = $_;
"$key: " .
join(", " =>
map { my $value = $data{$key}{$_} // "";
qq|$_ is "$value"|
}
@subkeys) .
"\n"
}
sort keys %data;
Выход:
KEY1: SUBKEY1 is "Canada", SUBKEY2 is "50.00", SUBKEY3 is "75.00"
KEY2: SUBKEY1 is "Mexico", SUBKEY2 is "", SUBKEY3 is "200.00"
KEY3: SUBKEY1 is "", SUBKEY2 is "150.00", SUBKEY3 is ""