您的变量命名不当。重用$states 作为州名?哎哟。
my $find = "ISO2:4166-23:US";
my $found_state_name;
while ( my ($country_name, $states) = each(%$VAR1) ) {
while (my ($state_name, $state) = each(%$states) ) {
while ( my ($key, $value) = each(%$state) ) {
if ($value eq $find) {
$found_state_name = $state_name;
}
}
}
}
现在,最好在找到结果后立即停止搜索。我们不能在仍然使用each 的情况下这样做(因为稍后会在这些哈希上搞砸keys/values/each)。
my $find = "ISO2:4166-23:US";
my $found_state_name;
FIND:
for my $country_name (keys(%$VAR1)) {
my $country = $VAR1->{$country_name};
for my $state_name (keys(%$country)) {
my $state = $country->{$state_name};
for my $key (keys(%$state)) {
if ($state->{$key} eq $find) {
$found_state_name = $state_name;
last FIND;
}
}
}
}
我们从不使用$country_name 或$key,除非是为了获取价值。
my $find = "ISO2:4166-23:US";
my $found_state_name;
FIND:
for my $states (values(%$VAR1)) {
for my $state_name (keys(%$states)) {
my $state = $country->{$state_name};
for my $value (values(%$state)) {
if ($value eq $find) {
$found_state_name = $state_name;
last FIND;
}
}
}
}
如果您知道要查找 ISO2 值,则可以简化为以下内容:
my $find = "ISO2:4166-23:US";
my $found_state_name;
FIND:
for my $states (values(%$VAR1)) {
for my $state_name (keys(%$states)) {
my $state = $states->{$state_name};
if ($state->{ISO2} eq $find) {
$found_state_name = $state_name;
last FIND;
}
}
}
你想使用grep,嗯?由于您需要一个州名,因此我们需要 grep 一个州名列表。
my @state_names = ...;
my ($found_state_name) =
grep { ... }
@state_names;
我们可以使用获取状态名称列表
my @state_names =
map { keys(%$_) }
values(%$VAR1);
但这还不足以执行检查。 (现在,我假设只需要检查 ISO2 属性。)
my @state_names =
map { keys(%$_) }
values(%$VAR1);
my ($found_state_name) =
grep { $VAR1->{???}{$_}{ISO2} eq $find }
@state_names;
有两种解决方案。您可以使用国家/地区对。
my @country_state_name_pairs =;
map {
my $country_name = $_;
map { [ $country_name, $_ ] }
keys(%{ $VAR1->{$country_name} )
}
keys(%$VAR1);
my ($found_state_name) =
map { $_->[1] }
grep {
my ($country_name, $state_name) = @$_;
$VAR1->{$country_name}{$state_name}{ISO2} eq $find
}
@country_state_name_pairs;
或者您可以创建一个平面列表并进行搜索。
my @states_with_name =
map { [ $_, $VAR1->{$_} ] }
values(%$VAR1);
my ($found_state_name) =
map { $_->[0] }
grep { $_->[1]{ISO2} eq $find }
@states_with_name;
注意阻止我们合并这两个语句。
my ($found_state_name) =
map { $_->[0] } # Get the state name.
grep { $_->[1]{ISO2} eq $find } # Filter out undesireable states.
map { [ $_, $VAR1->{$_} ] } # $state_name => [ $state_name, $state ]
values(%$VAR1); # Get the countries.
最后一个还不错!
最后,有两种方法可以修改上面的每一个来搜索所有字段,而不仅仅是ISO2)。 (我将只对上述两种解决方案中的后者进行修改。)
my ($found_state_name) =
map { $_->[0] } # Get the state name.
grep { # Filter out undesireable states.
grep { $_ eq $find } # Filter out undesireable properties of the state.
values(%{ $_->[1] }) # Get the state's property values.
}
map { [ $_, $VAR1->{$_} ] } # $state_name => [ $state_name, $state ]
values(%$VAR1); # Get the countries.
或
my ($found_state_name) =
map { $_->[0] } # Get the state name.
grep { $_->[1] eq $find } # Filter out undesireable states.
map { # $state_name => multiple [ $state_name, $value ]
my $state_name = $_;
map { [ $state_name, $_ ] } # value => [ $state_name, $value ]
values(%{ $VAR1->{$_} ) # Get the state's property values.
}
values(%$VAR1); # Get the countries.
这些是不可读的。最好避免使用它们。
最后,如果您要根据ISO2 执行多次搜索,最好按照ISO2 组织数据。
my %by_iso2 = (
'ISO2:4166-23:US' => {
country_name => 'USA',
state_name => 'Alabama',
ISO2 => 'ISO2:4166-23:US',
ISO3 => 'ISO3:3166-2:US',
...
},
'ISO2:4166-23:US' => {
country_name => 'USA',
state_name => 'Washington',
ISO2 => 'ISO2:30-23:US',
ISO3 => 'ISO3:40-166-2:US',
...
},
...
);