2012-03-15 8 views
2

perlのハッシュでキーと値を入れ替えて新しいハッシュを作成したい。これは、重複する値のキーが配列に入れられるように行われることに注意してください。これはreverseとは異なります。perlのハッシュでスワッピングキーと値を書き込む最もコンパクトな方法

私は明らかにこのためのループを行うことができます。しかし、私はそれがmapなどを使用してコンパクトな形で行うことができるかどうかはわかりません。

ありがとう。

+2

「コンパクト」を定義します。なぜこれが賞賛できる目標であるか教えてください。短いと読めない私の評点の本のポイントを失う。 – tchrist

+0

@tchrist:私は、「より機能的な」と言っていました。私は明示的なループを避けることは、matlab、R、python、perlのような言語でいくつかの効率を得ることができると信じています。たぶんすべての場合ではないかもしれませんが、一般的には真です。私は正しい? –

+0

いいえ、正しくはありません。それが効率のためではなく、あなたにとって理にかなったコードを作るなら、それを行います。 – ysth

答えて

8

このような "コンパクト"ループを実行できます。

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

「反転」ハッシュのすべての値は、この配列になります。

+0

ありがとうございます。それは基本的に私がループアプローチで言ったことです。私が尋ねようとしているのは、 '%orig = map {$ orig {$ _} => $ _}のように新しいハッシュを宣言したり、 orig); '? –

+0

私には分かりません。新しいハッシュを宣言することであなたの問題は何ですか? – Mat

1

機能性?ハッシュデリファレンスで減らすの呼び出しをラップするいくつかの理由

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 = %{ 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 
    } 
}; 

きれい:いくつかの他の発現からの結果は、Perlをふり元ハッシュpairlistsを有する場合%の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; 
関連する問題