シュワルツ変換はどうですか?
#! /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;
シュワルツ変換を後ろから前に読むことを忘れないでください。最初の (最後に最も近い) <code>map は%data
、不特定の順序でレコードのリストにフラット化または「非正規化」します。map
サブキーに到達するには、入れ子になっている必要があります。任意の深いネストを処理するには、flatten
再帰的に定義します。
使用されるすべてのサブキーを収集するために以前のパスを作成したため、特定のサブキーが存在しない場合、の値$data{$key}{$_}
は未定義の値になります。//
バージョン 5.10.0 で新しく追加された定義済み OR 演算子を使用して、デフォルト値の を指定します""
。
フォームの平坦化されたレコードを使用
[ "KEY1", "SUBKEY3", "75.00" ],
[ "KEY1", "SUBKEY1", "Canada" ],
...
並べ替えは簡単です。それぞれの最初の要素 (キー) を比較し、それらが等しい場合は、秒 (サブキー) に戻ります。
最後に、最も外側map
で、ソートされた非正規化レコードを出力用にフォーマットし、結果のリストを演算子を介して標準出力にprint
渡します。
出力:
KEY1: SUBKEY1 は「カナダ」
KEY1: SUBKEY2 は「50.00」
KEY1: SUBKEY3 は「75.00」
KEY2: SUBKEY1 は「メキシコ」
KEY2: サブキー2 は ""
KEY2: SUBKEY3 は「200.00」
KEY3: サブキー1は「」
KEY3: サブキー2は「150.00」
KEY3: サブキー3 は ""
サブキーをそれぞれのキーと同じ行にグループ化するには、次のようなコードを使用します。
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 は「カナダ」、SUBKEY2 は「50.00」、SUBKEY3 は「75.00」
KEY2: SUBKEY1 は「メキシコ」、SUBKEY2 は「」、SUBKEY3 は「200.00」
KEY3: SUBKEY1 は「」、SUBKEY2 は「150.00」、SUBKEY3 は「」