Perl一次创建哈希引用并循环遍历每个分支中的一个元素

时间:2013-04-09 16:13:16

标签: perl loops hash for-loop hash-reference

作为一名初学者,我认为这是一个相当复杂的问题,我希望有人可以提供帮助。

我有以下文本文件(tab delminated)...

FILE1.TXT

Dog     Big     
Dog     Medium     
Dog     Small     
Rabbit     Huge     
Rabbit     Tiny     
Rabbit     Middle    
Donkey     Massive    
Donkey     Little   
Donkey     Gigantic

我需要将FILE1.txt读入哈希引用以获得类似以下内容的...(使用Data :: Dumper)

$VAR1 = {
        'Dog' => {
                 'Big',
                 'Medium',
                 'Small'
                 },
        'Rabbit  => {
                    'Huge',
                    'Tiny',
                    'Middle'
                    },
        'Donkey  => {
                    'Massive',
                    'Little',
                    'Gigantic'
                    },                               
        };

我遇到的问题:

然后我需要一次循环遍历散列引用的每个分支,我将使用散列引用中的值来检查这是否与我的关键字匹配,如果是,则它将返回它的相应密钥....例如......

我需要做什么:

my $keyword == "Little";

Dog->Big 
if 'Big' matches my keyword then return $found = Dog
else go to the next branch
Rabbit->Huge
if 'Huge' matches my keyword then return $found = Rabbit
else go to the next branch
Donkey->Massive
if 'Massive' matches my keyword then return $found = Donkey
else go to the next branch (which is Dog again, but the second element this time)
Dog->Medium
if 'Medium' matches my keyword then return $found = Dog
else go to the next branch
Rabbit->Tiny
if 'Tiny' matches my keyword then return $found = Rabbit
else go the the next branch
Donkey->Little
if 'Little' matches my keyword then return $found = Donkey

.....等等,直到找到关键字或者我们到达哈希引用的末尾

这是我试图实现的那种但不知道如何去做,或者哈希引用是否是最好的方法,或者它是否可以完成哈希/哈希引用?

非常感谢您对此的帮助,谢谢

2 个答案:

答案 0 :(得分:1)

批评我自己的答案:进行搜索的部分的结构可能更好。也许即使使用有序散列也没有意义,因为搜索是通过线性列表。也许它应该是一个数组数组

   use strict;
    use warnings;
    use Tie::IxHash;
    #open file
    open(my $fh,"ani.txt") ||die $!;

    #make an ordered hash
    tie my %sizes, 'Tie::IxHash';


    #read file into hash of arrays
    while(<$fh>) {
       (my $animal,my $size)=split(/\s+/);
       if (!exists($sizes{$animal})) {
           $sizes{$animal} = [$size];
       } else { 
           push @{$sizes{$animal}},$size;
       }
    }

    my $keyword="Little";
    my $running=1;
    my $depth=0;
    while( $running ) {
      $running = 0;
      for my $search (keys %sizes) {
          next if ($depth > @{$sizes{$search}});
          $running = 1;
          if ($keyword eq $sizes{$search}[$depth]) {
              print "FOUND!!!!!! $search $depth";
              exit(0);
          }
      }
      $depth++;
    }

这是针对所述问题的解决方案的另一版本。为解决实际问题,除了散列中每只动物的第一个“大小”键外,不需要存储任何东西

然后可以通过该哈希来查找动物

use strict;
use warnings;
open(my $fh,"ani.txt") ||die $!;

my %animals;

#read file into hash
while(<$fh>) {
   (my $animal,my $size)=split(/\s+/);
   #only add the animal the first time the size is found
   if (!exists($animals{$size})) {
       $animals{$size} = $animal;
   } 
}

my $keyword="Little";
print "animal is ", $animals{$keyword};

答案 1 :(得分:1)

选择正确的数据结构通常是解决方案的关键步骤,但首先您应该定义您尝试实现的目标。总体目标是什么?例如,我有这个数据文件,在我的应用程序/程序中,我经常需要这些信息。提出正确的问题至关重要,因为例如,如果您不需要经常询问关键字,那么创建哈希是没有意义的。

 perl -anE'say $F[0] if $F[1] eq "Little"' FILE1.txt

是的就是这么简单。在perlrun联机帮助页中查看切换及其含义以及如何在更大的应用程序中执行相同的操作。

如果您经常需要提出这个问题,您应该安排您的数据,以帮助您而不是您必须与之抗争。

use strict;
use warnings;
use feature qw(say);
use autodie;

open my $f, '<', 'FILE1.txt';
my %h;
while(<$f>) {
    chomp;
    my ($animal, $keyword) = split' ';
    $h{$keyword} = $animal unless exists $h{$keyword};
}

close $f;

for my $keyword (qw(Little Awkward Small Tiny)) {
    say $h{$keyword} ? "$keyword $h{$keyword}" : "keyword $keyword not found";
}

但是如果你仍然坚持想要遍历哈希,你可以做到,但你已经被警告了。

open my $f, '<', 'FILE1.txt';
my %h;
while (<$f>) {
    chomp;
    my ( $animal, $keyword ) = split ' ';
    push @{ $h{$animal} }, $keyword;
}

close $f;

KEYWORD:
for my $keyword (qw(Little Awkward Small Tiny)) {
    for my $animal (keys %h) {
        for my $k (@{$h{$animal}}) {
            if($k eq $keyword) {
                say "$keyword $animal";
                next KEYWORD;
            }
        }
    }
    say "keyword $keyword not found";
}