【问题标题】:Inserting and iterating over hash of arrays插入和迭代数组的哈希
【发布时间】:2018-08-01 10:46:59
【问题描述】:

我有以下输入数据

Country1:operator1
Country1:operator2
Country1:operator3

Country2:operator1
Country2:operator2
Country2:operator3

我想将此数据插入到哈希 %INFO 中,这样每个键都对应一个“运算符”数组,因此我可以按以下方式进行迭代

foreach $i ( keys %INFO ) {

    foreach $operator ( $INFO{$i} ) {
        print " $i ---> $operator \n";  
    }
}

这是我自己的无法正常工作的解决方案

open($fh, "$info_file");

while (my $row = <$fh>) {
    chomp $row;
    @tokens = split(":",$row);

    $name     = $tokens[0];
    $operator = $tokens[2];

    if ($name =~ /^[A-Z]/) {

        if ( exists $INFO{$name} ) {
            $ptr = \$INFO{$name};
            push(@ptr, $operator);
        }
        else {
            @array = ( "$operator" );
            $INFO{$name} = [ @array ];
        }
    }
}

close($f);

【问题讨论】:

    标签: perl perl-hash


    【解决方案1】:

    恐怕你过于复杂了。

    open my $fh, '<', $info_file or die "Can't open '$info_file': $!";
    
    my %info;
    
    while (<$fh>) {
      next unless /^[A-Z]/;
      chomp;
      my ($name, $operator) = split /:/;
      push @{ $info{$name} }, $operator;
    }
    

    并访问它:

    foreach my $i (keys %info) {
      foreach my $op (@{ $info{$i} }) {
        say "$i ----> $op";
      }
    }
    

    如果您将哈希值视为数组引用,那么 Perl 会将其设为数组引用。

    有关详细信息,请参阅Perl Data Structures Cookbook

    【讨论】:

    • 非常非常干净,很好。感谢您的帮助。(无论出于何种原因,拆分附近的等号不可见。)
    【解决方案2】:

    好吧,首先这段代码有很多错误,使用open的三输入形式并且默认不引用变量,Perl知道什么时候应该是字符串。所以open($fh,"$info_file"); 应该是open($fh, '&lt;', $info_file);

    第二次拆分默认不返回分隔符,所以$operator = $tokens[2];应该是$operator = $tokens[1];

    第三,你为什么忽略文件中不以 A 到 Z 开头的国家?

    第四次使用自动激活,因此整个if else 块可以被push @{$INFO{$name}}, $operator 替换

    第五个$ptr@ptr 是单独的变量,将数组引用分配给$ptr 并不能使其在@ptr 中可用,\$INFO{$name} 也引用了$INFO{$name} 是什么,在你的case 已经是一个数组引用,因此您在$ptr 中获得了对数组引用的引用,如果您保留此代码,则应该写为$ptr = $INFO{$name};

    第六次分配给@array 是多余的,else 子句中的两行应该写成$INFO{$name} = [ $operator ];

    通过所有这些更改,您将获得

    open($fh, '<', "$info_file");
    while (my $row = <$fh>) {
        chomp $row;
        my @tokens = split(":",$row);
        $name = $tokens[0];
        $operator = $tokens[1];
        if ($name =~ /^[A-Z]/) {
            push @{$INFO{$name}}, $operator;
        }
    }
    close($f);
    

    【讨论】:

      【解决方案3】:

      您已经非常接近了,但不需要显式使用引用或将哈希值初始化为空数组

      这就是你所需要的

      use strict;
      use warnings 'all';
      
      open my $fh, '<', $info_file or die $!;
      
      my %info;
      
      while ( <$fh> ) {
          chomp;
          my ($name, $operator) = split /:/;
          push @{ $info{$name} }, $operator if $name =~ /^[A-Z]/;
      }
      

      【讨论】:

        猜你喜欢
        • 2014-12-15
        • 2019-04-06
        • 2013-04-30
        • 2015-11-08
        • 2011-04-08
        • 1970-01-01
        • 1970-01-01
        • 2016-06-23
        • 2019-06-03
        相关资源
        最近更新 更多