Perl相当于(Python-)列表理解

Perl相当于(Python-)列表理解,python,perl,list-comprehension,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 从一个角度来看,我只想要值为None或undef的键。从另一个角度来看,我想要的是一个简洁的perl等价物。使用:

我正在寻找用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
从一个角度来看,我只想要值为None或undef的键。从另一个角度来看,我想要的是一个简洁的perl等价物。

使用:

Grep返回右侧列表中的值,其中大括号中的表达式的计算结果为真值。正如所指出的,您希望确保理解Perl中的真/假值。对Perl中的真理有很好的概述

您可能需要查看,它将大括号中的表达式应用于列表的每个元素并返回结果。例如:

my @data = ("A" => 0, "B" => 1, "C" => 0 );
my @modified_data = map { $data{$_} + 1 } @data;
print join ' ', @data, "\n";
print join ' ', @modified_data, "\n";
我想你想要:


我还认为我打字太慢,应该在发布答案之前重新加载页面。顺便说一句,值
0
undef
都是处理空值的好方法,但要确保记住使用的是哪个。假值和未定义值在Perl中不是一回事。澄清一下:
undef
在布尔测试中返回false,但是
0
也返回false。如果
0
是一个有效值,那么您需要显式地测试定义性,而不仅仅是真实性。(我提到它是因为James选择了
0
,而我选择了另一种方式,你可能知道这是否重要。)

关于主题的变化,请看一下(参见其实现和)


Moose::Autobox带有键/值“kv”,使代码更简洁:

my $key_list = %data->kv->grep( sub{ defined $_->[1] } )->map( sub{ $_->[0] } );
下面是上述内容的一个更明确、甚至更长的版本:

my $key_list = %data->kv
                    ->grep( sub { my ($k, $v) = @$_; defined $v } )
                    ->map(  sub { my ($k, $v) = @$_; $k }         );

酷。我很少在Perl中看到“非m//”广义grep。我通常使用“map”来表示这样的内容,并使用类似于:{?$\()}的块。我猜是TMTOWTDI:-)@Roboprog-谢谢。我认为这更简洁,但你的方式也绝对不错@你能举个更具体的例子吗?这是怎么回事!!角色?它是Perl,所以我很想试试它。:)@James Thompson:()列表上下文中的x是列表重复运算符!!()布尔化;任何true变为1,任何false变为(在()x提供的数字上下文中)0。所以grep{xxx}等价于map{($\ux)x!!(xxx)},因为当xxx为false时,$\ux将重复0次,当xxx为true时重复一次。我对使用map做grep的想法开了个玩笑,用了一种更愚蠢的方法。如果我理解的话,
[f(x)| x在list中,pred(x)]
可以被编码为
map{f(x)x!!pred(x)}list
酷!!你打字慢并不重要,反正你会得到更多的选票这很奇怪,因为我们写了基本相同的答案。我在这里完全没有投票权。我认为这是一个迹象,表明这个站点上的Perl程序员在这个例子中认为undef>0-PChris在这里一针见血。我确实吸取了教训。:)投票很奇怪。没什么大不了的,反正你有很好的答案,所以我不介意。是的,两个提议的解决方案非常相似,但我认为关于undef的说明很有帮助,所以我会支持多数票。谢谢大家!您的意思是要排除值为None或undef的键吗?你的例子就是这么做的。事后看来,这听起来确实很模棱两可。我猜“我想要钥匙”指的是“我想要它们——这样我就可以过滤掉它们”,但得到答案的问题是正确的:如何在一行中从收藏中挑选某些东西。抱歉:)通常我使用
map{f($\u)}grep{cond($\u)}@list
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
my $key_list = %data->kv->grep( sub{ defined $_->[1] } )->map( sub{ $_->[0] } );
my $key_list = %data->kv
                    ->grep( sub { my ($k, $v) = @$_; defined $v } )
                    ->map(  sub { my ($k, $v) = @$_; $k }         );