самый компактный способ записи ключей и значений в хэше в perl - PullRequest
2 голосов
/ 15 марта 2012

Я хочу создать новый хеш, меняя ключи и значения в хэше в perl.Обратите внимание, что это должно быть сделано так, чтобы ключи для дублированных значений помещались в массив, который отличается от того, что делает reverse.

Я, очевидно, могу сделать цикл для этого.Но я не уверен, что это можно сделать в компактной форме, например, используя map и т. Д.

Спасибо.

Ответы [ 2 ]

8 голосов
/ 15 марта 2012

Вы можете сделать такой "компактный" цикл, как этот;

my %orig = # whatever
my %rev;
push @{$rev{$orig{$_}}}, $_ for keys %orig;

Обратите внимание, что все значения "обращенного" хеша будут массивами с этим.

1 голос
/ 16 марта 2012

Функционально, как это?

my %orig = ( 1 => 'a', 2 => 'b', 3 => 'c', 65 => 'a' );
my $new_hash = List::Util::reduce { push @{ $a->{$orig{$b}} }, $b; $a } {}, keys %orig;

По какой-то причине завершение вызова приведения в разыменование хеша, похоже, нарушает магию & -prototype, но вы можете избежать новой переменной:

%orig = %{ List::Util::reduce sub { push @{ $a->{$orig{$b}} }, $b; $a }, {}, keys %orig };

Если вы хотите избежать внутренней ссылки на% orig, скажите, если исходный хеш-результат является результатом какого-то другого выражения, притвориться, что perl имеет pairlists:

%orig = %{ List::Util::reduce sub { push @{ $a->{ $b->[0] } }, $b->[1]; $a }, {},
    @{ List::Util::reduce sub { ! @$a || $#{ $a->[-1] } ? push @$a, [ $b ] : push @{ $a->[-1] }, $b; $a }, [],
        reverse %orig
    }
};

красивее с некоторыми полезными функциями:

sub flatten_hashref { %{$_[0]} }
sub flatten_arrayref { @{$_[0]} }
sub pairlist { reduce { ! @$a || $#{ $a->[-1] } ? push @$a, [ $b ] : push @{ $a->[-1] }, $b; $a } [], @_ }

%orig =
    flatten_hashref
    reduce { push @{ $a->{ $b->[0] } }, $b->[1]; $a } {},
    flatten_arrayref
    pairlist
    reverse
    %orig;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...