13

我正在寻找在 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

因此,以一种方式看待它,我只想要值为Noneundef的键。换一种方式来看,我想要的是简洁的 perl 等效于带有条件的列表理解

4

3 回答 3

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;

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

于 2009-07-10T23:46:05.037 回答
13

使用grep

#!/usr/bin/perl

use strict;
use warnings;

my %data = ("A" => 0, "B" => "yes", "C" => 0 );
my @keys = grep { $data{$_} } keys %data;

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";
于 2009-07-10T23:42:52.097 回答
6

有关主题的变化,请查看autobox(请参阅其实现 autobox::CoreMoose::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


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 }         );
于 2009-07-11T13:03:46.453 回答