con*_*nny 13 python perl list-comprehension
我正在寻找在Perl中表达这个Python片段的方法:
data = {"A": None, "B": "yes", "C": None}
key_list = [k for k in data if data[k]]
# in this case the same as filter(lambda k: data[k], data) but let's ignore that
Run Code Online (Sandbox Code Playgroud)
所以从一个方面来看,我只想要值为None或undef的键.从另一个角度来看,我想要的是简洁的perl相当于有条件的列表理解.
Tel*_*hus 21
我想你想要grep:
#!/usr/bin/env perl
use strict;
use warnings;
my %data = ( A => undef, B => 'yes', C => undef );
my @keys = grep { defined $data{$_} } keys %data;
print "Key: $_\n" for @keys;
Run Code Online (Sandbox Code Playgroud)
我也认为我打字太慢了,我应该在发布答案之前重新加载页面.顺便说一句,要么值0或者undef可以是处理空值的好方法,但要确保记住你正在使用的是什么.错误值和未定义的值在Perl中不是一回事.澄清:undef在布尔测试中返回false,但也是如此0.如果0是有效值,那么您希望显式测试定义,而不仅仅是真实.(我提到它是因为詹姆斯去了0,我走了另一条路,你可能会或可能不知道它是否重要.)
Jam*_*son 13
使用grep:
#!/usr/bin/perl
use strict;
use warnings;
my %data = ("A" => 0, "B" => "yes", "C" => 0 );
my @keys = grep { $data{$_} } keys %data;
Run Code Online (Sandbox Code Playgroud)
Grep返回右侧列表中的值,其中大括号中的表达式求值为真值.正如telemachus指出的那样,您希望确保您了解Perl中的真/假值.这个问题很好地概述了Perl中的真相.
您可能需要查看map,它将括号中的表达式应用于列表的每个元素并返回结果.一个例子是:
my @data = ("A" => 0, "B" => 1, "C" => 0 );
my @modified_data = map { $data{$_} + 1 } @data;
print join ' ', @data, "\n";
print join ' ', @modified_data, "\n";
Run Code Online (Sandbox Code Playgroud)
有关主题的变化,请查看autobox(请参阅其实现 autobox :: Core和Moose :: Autobox)
use autobox::Core;
my %data = ( A => undef, B => 'yes', C => undef );
my $key_list = %data->keys->grep( sub { defined $data{$_} } );
say "Key: $_" for @$key_list;
# => Key: B
Run Code Online (Sandbox Code Playgroud)
Moose :: Autobox附带键/值'kv',使代码DRYer:
my $key_list = %data->kv->grep( sub{ defined $_->[1] } )->map( sub{ $_->[0] } );
Run Code Online (Sandbox Code Playgroud)
这是上面更明确甚至更长的版本:
my $key_list = %data->kv
->grep( sub { my ($k, $v) = @$_; defined $v } )
->map( sub { my ($k, $v) = @$_; $k } );
Run Code Online (Sandbox Code Playgroud)