値をキーにし、キーを値にしたいのですが。これを行うための最良の方法は何ですか?
http://www.dreamincode.net/forums/topic/46400-swap-hash-values/ から適応:
ハッシュが$hash
に保存されていると仮定します。
while (($key, $value) = each %hash) {
$hash2{$value}=$key;
}
%hash=%hash2;
reverse( http://www.misc-Perl-info.com/Perl-)を使用すると、はるかに洗練されたソリューションを実現できるようです。 hashes.html#reverseph ):
%nhash = reverse %hash;
逆にすると、重複する値が上書きされることに注意してください。
reverse
を使用します:
use Data::Dumper;
my %hash = ('month', 'may', 'year', '2011');
print Dumper \%hash;
%hash = reverse %hash;
print Dumper \%hash;
前述のように、最も単純なのは
my %inverse = reverse %original;
複数の要素が同じ値を持つ場合、「失敗」します。その状況を処理するためのHoAを作成できます。
my %inverse;
Push @{ $inverse{ $original{$_} } }, $_ for keys %original;
だからあなたはハッシュに逆キーと値が欲しいですか?したがって、リバースを使用してください...;)
%hash2 = reverse %hash;
元に戻す(k1 => v1、k2 => v2)-歩留まり(v2 => k2、v1 => k1)-そしてそれがあなたが望むものです。 ;)
my %orig_hash = (...);
my %new_hash;
%new_hash = map { $orig_hash{$_} => $_ } keys(%orig_hash);
Map-over-keysソリューションはより柔軟です。あなたの価値が単純な価値ではない場合はどうなりますか?
my %forward;
my %reverse;
#forward is built such that each key maps to a value that is a hash ref:
#{ a => 'something', b=> 'something else'}
%reverse = map { join(',', @{$_}{qw(a b)}) => $_ } keys %forward;
_Hash::MultiValue
_ を使用してこれを行う方法は次のとおりです。
_use experimental qw(postderef);
sub invert {
use Hash::MultiValue;
my $mvh = Hash::MultiValue->from_mixed(shift);
my $inverted;
$mvh->each( sub { Push $inverted->{ $_[1] }->@* , $_[0] } ) ;
return $inverted;
}
_
これをテストするには、次のことを試してください。
_my %test_hash = (
q => [qw/1 2 3 4/],
w => [qw/4 6 5 7/],
e => ["8"],
r => ["9"],
t => ["10"],
y => ["11"],
);
my $wow = invert(\%test_hash);
my $wow2 = invert($wow);
use DDP;
print "\n \%test_hash:\n\n" ;
p %test_hash;
print "\n \%test_hash inverted as:\n\n" ;
p $wow ;
# We need to sort the contents of the multi-value array reference
# for the is_deeply() comparison:
map {
$test_hash{$_} = [ sort { $a cmp $b || $a <=> $b } @{ $test_hash{$_} } ]
} keys %test_hash ;
map {
$wow2->{$_} = [ sort { $a cmp $b || $a <=> $b } @{ $wow2->{$_} } ]
} keys %$wow2 ;
use Test::More ;
is_deeply(\%test_hash, $wow2, "double inverted hash == original");
done_testing;
_
ここでギミックテストに合格するために、invert()
関数は値として配列参照を持つ_%test_hash
_に依存していることに注意してください。ハッシュ値が配列参照でない場合にこれを回避するには、通常/混合ハッシュを複数値ハッシュに「強制」して、_Hash::MultiValue
_がオブジェクトに祝福できるようにします。ただし、このアプローチでは、単一の値でも配列参照として表示されます。
_for ( keys %test_hash ) {
if ( ref $test_hash{$_} ne 'ARRAY' ) {
$test_hash{$_} = [ $test_hash{$_} ]
}
}
_
これは長い間:
_ref($_) or $_ = [ $_ ] for values %test_hash ;
_
これは、「往復」テストに合格するためにのみ必要です。