Perl-эквивалент (Python-) понимания

Я ищу способы выразить этот фрагмент Python в Perl:

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 ignore that

Поэтому, глядя на него в одну сторону, мне просто нужны ключи, где значения равны None или undef. Если посмотреть на это по-другому, то я хочу, это сжатый эквивалент pera с условным.

Ответы

Ответ 1

Я думаю, вы хотите 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 может быть хорошим способом обработки нулевых значений, но обязательно помните, что вы используете. Значение false и значение undefined не совпадают с Perl. Чтобы уточнить: undef возвращает false в булевом тесте, но также 0. Если 0 - допустимое значение, вы хотите явно проверить определенность, а не просто правду. (Я упоминаю об этом, потому что Джеймс пошел за 0, и я пошел в другую сторону, и вы можете или не знать, имеет ли это значение.)

Ответ 2

Используйте grep:

#!/usr/bin/perl

use strict;
use warnings;

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

Grep возвращает значения из списка в правой части, для которого выражение в фигурных скобках имеет значение true. Как указывает 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";

Ответ 3

Для изменения темы читайте 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


Moose:: Autobox поставляется с ключом/значением "kv", который делает код DRYer:

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 }         );