perl:子例程返回0而不是指定的数组

时间:2018-01-01 16:54:53

标签: perl loops hash subroutine

我有像这样的散列哈希:

my %HoH = (
    flintstones => {
        1 => "fred",
        2 => "barney",
    },
    jetsons => {
        1 => "george",
        2 => "jane",

    },
    simpsons => {
        1 => "homer",
        2 => "marge",
    },
);

我的子程序用于搜索指定键的值,例如搜索2的所有e,并在每种情况下返回密钥1的值。

它可以工作,因为它可以很好地打印这些东西,我也可以将它打印到文本文件中。我也希望将相同的行推送到数组@output

为什么我的子程序返回零,在这种情况下保存在$hej中。

sub search_hash {

    # Arguments are
    #
    # $hash=hash ref
    # $parameter1=key no. to search in
    # $parameter2=value to find
    # $parameter3=name of text file to write to

    my ( $hash, $parameter1, $parameter2, $parameter3 ) = @_, ;

    # Loop over the keys in the hash
    foreach ( keys %{$hash} ) {

        # Get the value for the current key
        my $value  = $hash->{$_};
        my $value2 = $hash->{'1'};

        search_hash( $value, $parameter1, $parameter2, $parameter3 );

        for my $key ( $parameter1 ) {

            my @output;    #create array for loop outputs to be saved

            if ( $value =~ $parameter2 ) {

                push @output, "$value2";    #push lines to array

                print "Value: $value\n";
                print "Name: $value2\n";

                open( my $fh, '>>', $parameter3 );
                print $fh ( "$value2\n" );
                close $fh;
            }

            return @output;
        }
    }
}

my $hej = search_hash( \%HoH, "2", 'e', 'data3.txt' );

print $hej;

输出

  

不能使用字符串(" fred")作为HASH参考,而#34; strict refs"在使用中

2 个答案:

答案 0 :(得分:1)

哈希的第一个循环中没有键“1”。递归子程序不是一个好选择。

my $value2 = $hash->{'1'};

Borodin的一行代码很棒。但我们应该搜索2秒。

  

在e中搜索所有2 s并在每种情况下返回键1的值。

总结一下,search_hash.pl

use strict;
use warnings;
use utf8;

my %HoH = (
  Flintstones => { 1 => "Fred",   2 => "Barney" },
  Jetsons     => { 1 => "George", 2 => "Jane"   },
  Simpsons    => { 1 => "Homer",  2 => "Marge"  }
  );

my @output2 = map { $_->{1} } grep { $_->{2} =~ /e/ } values %HoH;

open( my $fh, '>', "data3.txt");
print $fh ( "$_\n" ) foreach @output2;
close $fh;

并且

perl search_hash.pl
cat data3.txt

输出:

Fred
Homer
George

答案 1 :(得分:0)

子例程的返回表达式在与子例程本身相同的上下文中进行计算。由于您将子例程的结果假设为标量,因此在标量上下文中计算子例程,并在标量上下文中评估@output。在标量上下文中,数组返回它包含的元素数。在这种情况下,@output恰好为空,因此search_hash返回零。

如果您想要@output的元素而不是@output中的元素数,则需要在列表上下文中调用子例程。将结果分配给数组是这样做的一种方式。

这是我在下面发布的重写中修复问题的方法。请注意,我将标量$hej替换为下面的数组@hej

我还解决了其他问题。所有三个键中 1 的值 现在返回第二级哈希值,因为它们中的每一个都包含键 2 的值,其中包含 e (要查找的值)。见下文。

use strict;
use warnings;

my %HoH = (
  Flintstones => { 1 => "Fred",   2 => "Barney" },
  Jetsons     => { 1 => "George", 2 => "Jane"   },
  Simpsons    => { 1 => "Homer",  2 => "Marge"  }
);

sub search_hash {
  # Arguments:
  #  $hash:          hash ref
  #  $search_key:    key to search in each 2-nd level hash
  #  $search_string: value to find
  my ( $hash, $search_key, $search_string ) = @_;
  my @output;
  foreach ( keys %{$hash} ) {
    #print "Key: $_\n";
    my $hash2 = $hash->{$_};  # 2-nd level hash (reference to) 
    my $search_val = $hash2->{$search_key};  # Value for key == parameter1
    #print "Value: $search_val\n";
    if ($search_val =~ /\Q$search_string/) {
      my $id = $hash2->{'1'};
      #print "Name:  $id\n";
      push @output, $id;
    }
  }

  return @output;
}

my @hej = search_hash( \%HoH, '2', 'e' );
print "Result: @hej\n";