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