我一直在寻找使用perl函数map
执行以下操作的方法:
给定哈希,我想提取值等于或匹配指定参数的对(键,值)。
在我的例子中,我想提取{key,value}对value = failed
,但它也可以是一个表达式(即以A开头的字符串或REGEX)。这就是为什么我想要一个哈希值,而不仅仅是一个与值匹配的键表。
my %strings = (
bla => "success",
ble => "failed",
bli => "failed",
foo => "success",
blo => "failed",
bar => "failed",
blu => "success"
);
my %failed_s = ();
while (my ($k, $v) = each %strings) {
if ( $v eq 'failed' ) {$failed_s{$k} = $v};
};
我尝试了几种方法,但没有很好的结果,所以我觉得我对引用,矫揉造作,结果等感到困惑。
my %failed_s =
map { { $_ => $strings{$_} }
if ( $strings{$_}./failed/ ) }
keys %strings;
my %failed_s =
map { ( $strings{$_} eq 'failed') &&
($_, $strings{$_}) }
keys %strings;
print "Dumper \%failed_s: \n" . Dumper(\%failed_s);
在这种情况下,使用地图可能无效或无效,但它可以帮助我(可能还有其他人)知道原因。
答案 0 :(得分:8)
Perl很容易获得散列逻辑,以至于很少有人能够将Key-Value Pair概念与其最常见的实现区分开来:Hash。
因此,当大多数Perlers考虑KVP时,他们会认为是“哈希”。但想想Perl Arrays的方式1)列表,2)队列,3)堆栈,你会发现实现并不完全等同于概念。
我看到需要以哈希之外的方式处理对,所以我创建了自己的库,我打算将其上传到CPAN,直到我找到List::Pairwise
为止。
(当然它似乎没有我的“哈希拼接”方法......)
无论如何,使用List::Pairwise
,您只需
use List::Pairwise qw<grepp>;
my %failed_s = grepp { $b eq 'failed' } %strings;
当我说“看看它是多么简洁!”时,我觉得自己是一个电视购物的人。
答案 1 :(得分:6)
在第一个地图示例中,您将返回单个元素哈希引用,这不是您想要的。
在你的第二个中,&&
运算符在其参数上强制使用标量上下文,因此列表($_, $strings{$_})
仅返回列表中的最后一项。
您正在寻找的是:
my %failed_s = map {
$strings{$_} eq 'failed' ? ($_, $strings{$_}) : ()
} keys %strings;
如果条件为真,? :
运算符返回列表,如果为假,则返回空列表。
答案 2 :(得分:3)
map FUNC, LIST
对LIST中的每个元素进行操作。你的函数可以为一些元素返回一个空列表(正如Eric Strom的答案所示)。另一种方法是使用另一个过滤器,以便map
仅对您感兴趣的元素进行操作:
my %failed_s = map {
$_ => $strings{$_}
} grep { $strings{$_} eq 'failed' } keys %strings;
答案 3 :(得分:3)
我认为地图+ grep组合更清晰。
my %failed_s =
map { $_ => $strings{$_} }
grep { $strings{$_} eq 'failed' }
keys(%strings);
但是因为grep可以使用map实现,
my %failed_s =
map { $_ => $strings{$_} }
map { $strings{$_} eq 'failed' ? $_ : () }
keys(%strings);
只需使用地图即可完成。
my %failed_s =
map { $strings{$_} eq 'failed' ? ($_ => $strings{$_}) : () }
keys(%strings);
他们遇到的问题是,当你打算不归还任何东西时,你会返回假。