怎麼樣Schwartzian transform?
#! /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;
記得閱讀Schwartzian從後到前的變換。第一個最接近結尾的是map
將某個未指定順序的記錄列表展平或「非規範化」爲%data
。嵌套0是達到子項所必需的。要處理任意深度的嵌套,請遞歸定義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 ""
墨西哥在'$ data {KEY2}'中,但與您期望的輸出中的'KEY3'相關聯。 – 2010-07-08 19:29:15