将哈希值用作Perl中的类别

时间:2014-08-05 20:59:56

标签: perl hash

我正在将两个制表符分隔的文件读成两个哈希,文件如下所示:

apple fruit
pear  fruit
carrot vegetable
potato vegetable
peach fruit

apple 23
pear  34
carrot 12
potato 45
peach 12

我想只拿起蔬菜来获取他们的数字。有没有比通过周期更聪明的方式来做到这一点? 如果我想创建两个新的哈希%fruit和%vegetable,我真的必须这样做:

foreach (keys %kinds_hash) {
   if ($kinds_hash{$_} =~ "vegetable") {
      $vegetable{$_} = $numbers_hash{$_};
   } elsif ($kinds_hash{$_} =~ "fruit") {
      $fruit{$_} = $numbers_hash{$_};
   }
}

3 个答案:

答案 0 :(得分:0)

迭代所有值都没有错。

但是,如果您经常这样做,那么创建一个包含基于类型的名称数组的新数据结构可能会很有用。

use strict;
use warnings;

# Data in Paragraph mode
local $/ = '';

my %counts = split ' ', <DATA>;
my %types = split ' ', <DATA>;

# Create a structure that puts each type into an array
my %group_by_type;
while (my ($name, $type) = each %types) {
    push @{$group_by_type{$type}}, $name
}

# Show all Veges
for my $fruit (@{$group_by_type{vegetable}}) {
    print "$fruit $counts{$fruit}\n";
}

__DATA__
apple 23
pear 34
carrot 12
potato 45
peach 12

apple fruit
pear fruit
carrot vegetable
potato vegetable
peach fruit

输出:

carrot 12
potato 45

要了解有关阵列哈希和其他数据结构的更多信息,请查看perldsc - Perl Data Structures Cookbook

答案 1 :(得分:0)

您应该构建数据,以便尽可能简化您想要访问它的所有方式。

您想要访问vegetable类别中的所有项目以及所有这些项目的数字。为了简单起见,我将构建两个哈希 - 一个将项目的名称与其编号和类别相关联,另一个将类别与每个类别中的所有名称相关联。

此代码就是这样做的,并使用Data::Dump向您展示已构建的内容。

use strict;
use warnings;
use autodie;

my %items;
my %categories;

open my $fh, '<', 'numbers.tabsep';
while (<$fh>) {
  next unless /\S/;
  chomp;
  my ($name, $number) = split /\t/;
  $items{$name}[0] = $number;
}

open $fh, '<', 'categories.tabsep';
while (<$fh>) {
  next unless /\S/;
  chomp;
  my ($name, $cat) = split /\t/;
  $items{$name}[1] = $cat;
  push @{ $categories{$cat} }, $name;
}

use Data::Dump;
dd \%items;
dd \%categories;

<强>输出

{
  apple  => [23, "fruit"],
  carrot => [12, "vegetable"],
  peach  => [12, "fruit"],
  pear   => [34, "fruit"],
  potato => [45, "vegetable"],
}
{
  fruit => ["apple", "pear", "peach"],
  vegetable => ["carrot", "potato"],
}

现在,回答问题&#34;我想只拿起蔬菜并获取他们的数字&#34; 我们只是遍历{{1}的vegetable元素哈希,并使用%categories哈希来确定它们的数字。喜欢这个

%items

<强>输出

for my $item (@{ $categories{vegetable} }) {
  printf "%s %d\n", $item, $items{$item}[0];
}

工具已成功完成

答案 2 :(得分:0)

您可以创建哈希哈希,只需一个嵌套数据结构,其中内部键将是您的类别,值将是另一个哈希,其键将是类型,值是数字。

以下程序执行此操作:

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my %data; 

open my $fh_one, '<', 'file1';
while(<$fh_one>) {
    next unless /\S+/;
    chomp;
    my ($type, $category) = split /\t/;
    $data{$category}{$type} = undef;
}
close($fh_one);

open my $fh_two, '<', 'file2';
OUTER: while(<$fh_two>) {
    next unless /\S+/;
    chomp;
    my ($type, $number) = split /\t/;
    for my $category (keys %data) {
        for my $item (keys %{ $data{$category} }) {
            $data{$category}{$item} = $number and next OUTER if $item eq $type;
        }
    }
}
close($fh_two);

#print Dumper \%data;

while (my ($type, $number) = each $data{'vegetable'}) {
    print "$type $number\n";
}

如果取消注释print Dumper \%data;,您将看到嵌套的数据结构。它将如下所示:

$VAR1 = {
          'fruit' => {
                       'peach' => '12',
                       'apple' => '23',
                       'pear' => '34'
                     },
          'vegetable' => {
                           'carrot' => '12',
                           'potato' => '45'
                         }
        };

上述程序的输出是:

carrot 12
potato 45