我想通过在perl中的散列中交换键和值来创建新的哈希。请注意,这样做是为了将重复值的键放入数组中,这与reverse
不同。
我显然可以为此做一个循环。但我不确定它是否可以以紧凑的形式完成,例如使用map
等。
谢谢。
答案 0 :(得分:8)
你可以像这样做一个“紧凑”循环;
my %orig = # whatever
my %rev;
push @{$rev{$orig{$_}}}, $_ for keys %orig;
请注意,“反向”哈希的所有值都是带有此值的数组。
答案 1 :(得分:1)
这样的功能?
my %orig = ( 1 => 'a', 2 => 'b', 3 => 'c', 65 => 'a' );
my $new_hash = List::Util::reduce { push @{ $a->{$orig{$b}} }, $b; $a } {}, keys %orig;
出于某种原因,在hash-dereference中包含reduce调用似乎打破了& -prototype魔术,但你可以通过以下方式避免使用新变量:
%orig = %{ List::Util::reduce sub { push @{ $a->{$orig{$b}} }, $b; $a }, {}, keys %orig };
如果你想避免对%orig的内部引用,比如说原始哈希是来自其他表达式的结果,假装perl有pairlists:
%orig = %{ List::Util::reduce sub { push @{ $a->{ $b->[0] } }, $b->[1]; $a }, {},
@{ List::Util::reduce sub { ! @$a || $#{ $a->[-1] } ? push @$a, [ $b ] : push @{ $a->[-1] }, $b; $a }, [],
reverse %orig
}
};
更实用的一些实用功能:
sub flatten_hashref { %{$_[0]} }
sub flatten_arrayref { @{$_[0]} }
sub pairlist { reduce { ! @$a || $#{ $a->[-1] } ? push @$a, [ $b ] : push @{ $a->[-1] }, $b; $a } [], @_ }
%orig =
flatten_hashref
reduce { push @{ $a->{ $b->[0] } }, $b->[1]; $a } {},
flatten_arrayref
pairlist
reverse
%orig;