【问题标题】:Reversing a hash preserving Duplicate values反转保留重复值的哈希
【发布时间】:2015-05-10 09:59:57
【问题描述】:

我现有的哈希是

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

我想通过以下方式反转哈希

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

有人可以帮忙吗?

【问题讨论】:

  • What have you tried? SO 不是为我写一些代码的网站。您必须自己尝试,当您被困在某个地方时,请在此处说明您的问题,您将获得帮助。
  • 你应该展示一些你尝试过的工作。

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


【解决方案1】:

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

以下是一种方法:

#!/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

【讨论】:

  • 由于自动激活,因此无需在推入数组之前对其进行初始化。
  • 该死,你是对的!谢谢。我一直认为自动激活适用于“常规”标量,但如果你想要参考,你需要明确。我的错。而且我学到了一些东西。
【解决方案2】:

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

但是有一个数组references的散列。您可以像这样操作数组 ref:

#!/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;

因此,希望您能够了解创建所需数据结构所需的基础。提取您想要的值和键,创建一个数组 ref 并将它们插入到哈希中。或者迭代,并使用推送。

【讨论】:

  • 好答案。重要的是要指出嵌套数据结构中需要引用
【解决方案3】:

反转哈希是来自Perl Cookbook 的经典问题/方法。当反转为键的值是唯一的时,解决方案很简单。

%rev_hash  = reverse %hash ;

但是,正如您所注意到的,这种情况并不常见,因此此处其他答案中提供的解释/解决方案是必要的。一旦你理解了参考,它就不会太难(++ @Sobrique 用于制作这个链接)。

Cookbook 和其他 perl 资源有时会推荐 tie-ing 哈希(eg 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 有一些 neat new methods 用于 reverse-ing、inverting 和 flipping。

【讨论】:

    猜你喜欢
    • 2015-04-12
    • 2017-03-17
    • 2014-07-02
    • 2015-09-07
    • 2015-08-03
    • 1970-01-01
    • 1970-01-01
    • 2012-08-07
    • 2010-11-01
    相关资源
    最近更新 更多