3

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

我有以下文本文件(标签分层)...

文件1.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

.....依此类推,直到找到关键字或我们到达哈希引用的末尾

这是我想要实现但不知道如何去做的事情,或者哈希引用是否是最好的方法,或者它是否可以通过哈希/哈希引用来完成?

非常感谢您的帮助,谢谢

4

2 回答 2

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};
于 2013-04-09T19:32:54.390 回答
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";
}
于 2013-04-09T21:39:58.507 回答