我有这个:
%lookup = (
'Shelf' => { storage_types => 'Flat, Default' },
'Locker' => { storage_types => 'Valuable' },
);
我想得到这个:
%reverse_lookup = (
'Flat' => 'Shelf',
'Default' => 'Shelf',
'Valuable' => 'Locker',
);
我可以在测试中循环访问存储类型,并检查子例程是否返回正确的位置,例如。
我无法理解多列表扩展部分。
%reverse_lookup = map { split(/,\s*/, $lookup{$_}) => $_ } keys %lookup; # wrong
我想简单地使用地图或类似的东西,而不是foreach循环。
答案 0 :(得分:5)
你不能用单一地图做到这一点,因为它遍历%lookup hash的元素,而不是遍历里面的列表。因此,在这种情况下,您将在输出哈希中使用与源哈希中相同数量的键。
但是你可以使用嵌套映射 - 首先迭代主哈希元素,第二个迭代列表里面。
my %lookup = (
'Shelf' => { storage_types => 'Flat, Default' },
'Locker' => { storage_types => 'Valuable' },
);
my %reverse_lookup = map { my $key_name = $_; map {$_ => $key_name} (split(/,\s*/, $lookup{$_}->{storage_types})) } keys %lookup;
use Data::Dumper; print Dumper \%reverse_lookup;
P.S。 foreach有什么问题? :)
答案 1 :(得分:2)
将原始哈希修改为这样可能更容易:
%lookup = (
'Shelf' => { storage_types => [ 'Flat', 'Default'] },
'Locker' => { storage_types => ['Valuable'] },
);
然后
%reverse_lookup = map {
my $key = $_;
#$_ => $key foreach @{$lookup{$key}};
map { $_ => $key } @${lookup{$key}};
} keys %lookup;
答案 2 :(得分:1)
如果您只对storage_types
感兴趣并希望您有不可读的代码,可以尝试:
%reverse_lookup = map { my $k = $_; map { $_ => $k } split /,\s*/, $lookup{$_}{storage_types} } keys %lookup;
答案 3 :(得分:1)
事实证明,可以使用一张地图执行此操作,只要您不介意在void上下文中无用的地图(甚至是愚蠢的事情):
map { @reverse_hash{split /,\s*/, $lookup{$_}} = ($_x100) } keys %lookup;
但它简洁明了。它甚至可以工作!
答案 4 :(得分:0)
这是我编码的方式
use strict;
use warnings;
my %lookup = (
Shelf => { storage_types => 'Flat, Default' },
Locker => { storage_types => 'Valuable' },
);
my %reverse_lookup;
while ( my ($item, $info) = each %lookup ) {
my @types = split /,\s*/, $info->{storage_types};
$reverse_lookup{$_} = $item for @types;
}
use Data::Dump;
dd \%reverse_lookup;
<强>输出强>
{ Default => "Shelf", Flat => "Shelf", Valuable => "Locker" }