代码之家  ›  专栏  ›  技术社区  ›  yonetpkbji

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

  •  3
  • yonetpkbji  · 技术社区  · 13 年前

    作为一个初学者,我有一个我认为相当复杂的问题,我希望有人能帮助我。

    我有以下文本文件(制表符分层)。。。

    文件1.text

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

    我需要将FILE1.txt读取到哈希引用中,以获得如下内容。。。(使用数据::自卸车)

    $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 回复  |  直到 13 年前
        1
  •  1
  •   Hynek -Pichi- Vychodil Paulo Suassuna    13 年前

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

     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";
    }
    

    但如果你仍然坚持要遍历hash,你可以这样做,但你已经被警告了。

    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";
    }
    
        2
  •  1
  •   Vorsprung    13 年前

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

       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};