1

我有以下输入数据

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);
4

3 回答 3

3

恐怕你过于复杂了。

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 数据结构手册

于 2018-08-01T11:02:58.843 回答
2

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

默认情况下,第二次拆分不返回分隔符,因此$operator = $tokens[2];应该是$operator = $tokens[1];

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

第四次使用自动复活,所以整个if else方块都可以替换为push @{$INFO{$name}}, $operator

第五$ptr@ptr是单独的变量,将数组 ref 分配给$ptr它并不能使其可用,@ptr\$INFO{$name}引用了曾经$INFO{$name}的内容,在您的情况下,它已经是一个数组 ref,因此您正在获取对数组 ref 的引用,$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);
于 2018-08-01T11:21:11.007 回答
1

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

这就是你所需要的

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]/;
}
于 2018-08-01T11:36:50.210 回答