反转哈希保留重复值

时间:2015-03-09 09:33:34

标签: perl data-structures hash hashtable associative-array

我现有的哈希是

my $volvg = {
        'datavol' => 'oradatavg',
        'archvol' => 'archvg',
        'archvol1' => 'archvg',
        'soevol' => 'soevg',
        'redovol' => 'oradatavg'
};

我想以下列方式反转哈希

 $vgvol = { 'oradatavg' => [
                  'datavol',
                  'redovol'
                ], 'archvg' =>    [ 
                  'archvol',
                  'archvol1
                ] 'soevg' =>     [
                  'soevol'
                ] };

有人可以帮忙吗?

3 个答案:

答案 0 :(得分:2)

就地反转可能是一个坏主意,创建一个新哈希,然后如果你需要将它分配给旧哈希。

以下是一种方法:

#!/usr/bin/perl

use strict;
use warnings;


my $volvg = {
        'datavol' => 'oradatavg',
        'archvol' => 'archvg',
        'archvol1' => 'archvg',
        'soevol' => 'soevg',
        'redovol' => 'oradatavg'
};


my $reversed;
while( my( $k, $v)= each %$volvg)
  { # $reversed->{$v}||=[];   # not needed, see dgw's comment below
    push @{$reversed->{$v}}, $k; # push the old key into the array
  }

use DDP; p $reversed; # for checking the result
                      # you can also use Data::Dumper or other modules

答案 1 :(得分:1)

Perl中有点不清楚的是如何将数组嵌入到哈希中。因为从根本上说 - 你不能。没有数组哈希这样的东西。

但是,有一个数组引用的哈希。您可以像这样操作数组引用:

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper; 

my $array_ref = [ "one", "two" ]; 
print Dumper \$array_ref;

push ( @$array_ref, "three-ish" );
print Dumper \$array_ref;

my $hash_ref; 
$hash_ref->{"carrot"} = $array_ref; 
print Dumper \$hash_ref; 

push ( @{$hash_ref->{"carrot"}}, "a new value" );
print Dumper \$hash_ref;

希望您能够看到创建所需数据结构所需的基础。提取所需的值和键,创建数组引用并将它们插入到哈希中。或迭代,并使用推。

答案 2 :(得分:1)

反转哈希是Perl Cookbook中的经典问题/配方。当将值反转为键时,解决方案是微不足道的。

%rev_hash  = reverse %hash ;

但是,正如您所指出的那样,情况并非如此,因此这里的其他答案中提供的解释/解决方案是必要的。一旦你理解了引用,就不会太难了(++ @Sobrique来建立这个链接)。

Cookbook和其他perl资源有时会建议tie - 哈希(例如 cf Tie::RefHash)以便更轻松地使用引用

如果要反转一个本身包含引用的哈希,如果你必须深入哈希,那么它可能会很棘手。这是一个简单的示例,它应该将具有数组引用的散列反转为值。

use DDP;

my $volvg = {
  'datavol' => ['oradatavg', 'oradatavgpoo2'] ,
  'archvol' => 'archvg', 
  'archvol1' => 'archvg',
  'soevol' => 'soevg',
  'redovol' => 'oradatavg' };

while ( ($k,$v) = each(%$volvg) ) {  
   if (ref $v) { 
     map { push @{$volvg_rev{$_}}, $k }  @$v ;
   }  
   else { 
     push @{$volvg_rev{$v}}, $k  ;   
   } 
}

p $volvg ;
print "----\n";
p %volvg_rev ; 

<强>输出

  \ {
    archvol    "archvg",
    archvol1   "archvg",
    datavol    [
        [0] "oradatavg",
        [1] "oradatavgpoo2"
    ],
    redovol    "oradatavg",
    soevol     "soevg"
}
----
{
    archvg          [
        [0] "archvol1",
        [1] "archvol"
    ],
    oradatavg       [
        [0] "redovol",
        [1] "datavol"
    ],
    oradatavgpoo2   [
        [0] "datavol"
    ],
    soevg           [
        [0] "soevol"
    ]
}

另外,Perl6对reverse - ing,invertflip ping事件有一些neat new methods