【问题标题】:Dereferencing an array reference from a nested Perl hash从嵌套的 Perl 哈希中取消引用数组引用
【发布时间】:2016-04-25 17:00:02
【问题描述】:

我希望我已经正确地陈述了这个主题。我有一个通过读取文件构建的哈希值。外部散列是组,然后内部散列是该组内的参数。每个参数值可以是标量或数组,数组可以从 0 或 1 开始。

我编写了一个返回参数值的子程序。调用函数必须确定返回值是标量还是数组。适用于标量。返回对数组值的数组的引用(看起来像 ARRAY(0x004f00))。使用Data::Dumper 会吐出看起来像数组的数据,但我不知道如何在代码中取消引用它。有人可以指出我做错了什么吗?

%HoH = (
    flintstones => {
        husband     => "fred",
        possessions => [ undef, "car", "record player", "rock" ],
        pal         => "barney",
        pets        => [ "bird", "dinosaur" ],
    },
);

get_value("possessions");

sub get_value {

    my $what_i_want = shift;

    @groups = keys(%HoH);

    foreach my $group ( @groups ) {

        foreach my $param ( keys( %{ HoH {group} } ) ) {

            if ( $param eq $what_i_want ) {
                return $HoH{$group}{$param};
            }
        }
    }
}

调用者将返回值分配给数组@return,因此对于标量,它应该将值放入$return[0]

如果是数组,它应该填充数组。当我调用Dumper 时,它会打印出单引号中的标量和方括号中的数组,这是应该的。但是,当我使用 scalar(@return) 检查数组的大小时,它返回 1。

我尝试在末尾使用方括号取消对 return 语句的引用,看看是否可以返回一个标量,但没有运气。

【问题讨论】:

    标签: arrays perl hash hash-of-hashes


    【解决方案1】:

    你没有在上下文中显示被调用的子例程,但一个快速的解决方法是将它放在调用之后

    @return = @{ $return[0] } if ref $return[0]
    



    更新

    你错过了哈希的意义。您可以使用$what_i_want 作为哈希键访问参数哈希的正确元素

    我建议你把你的子程序代码改成这样

    for my $group ( keys %HoH ) {
    
        my $ret = $HoH{$group}{$what_i_want};
    
        return unless defined $ret;
        return ref $ret ? @$ret : $ret;
    }
    

    这样它就永远不会返回引用



    更新 2

    这是您按照我的建议修改的完整程序

    use strict;
    use warnings 'all';
    
    my %HoH = (
        flintstones => {
            husband     => "fred",
            possessions => [ undef, "car", "record player", "rock" ],
            pal         => "barney",
            pets        => [ "bird", "dinosaur" ],
        },
    );
    
    my @return = get_value('possessions');
    
    use Data::Dump;
    dd \@return;
    
    sub get_value {
    
        my ($wanted) = @_;
    
        for my $group ( keys %HoH ) {
    
            my $ret = $HoH{$group}{$wanted};
    
            if ( defined $ret ) {
                return ref $ret ? @$ret : $ret;
            }
        }
    
        return;
    }
    

    输出

    [undef, "car", "record player", "rock"]
    

    【讨论】:

    • 我不能直接复制代码,所以我不得不重新输入。添加了一点上下文,根据骆驼书示例修改。我同意您的方法会更容易,但该值不知道它所属的组(例如,Fred 不知道他在 Flintstones 上)。编辑:我明白你做了什么......太 Perlish 直观上是显而易见的。会试试的。谢谢!
    • “我无法直接复制代码” 您在与您的 Perl 开发相同的系统上没有 Web 浏览器吗? “该值不知道它所属的组”你误会了。您仍然需要遍历组,但您可以直接使用$what_i_want 作为参数哈希的键
    • 不,我的开发机器在一个隔离的网络上。我看到您在组中循环的位置,并且我确实了解哈希。我的 perl 很生锈(大约 10 年),我的书也很脏(2000 年),所以请原谅我的疏忽。所以我从中学到了一些东西,除了样式和删除内部循环之外,我看到的最大区别是return 语句。明天我会看看它,试图了解你做了什么以及它为什么有效。但它确实有效,为此我感谢你。
    • 解决方案的核心是ref $ret ? @$ret : $ret,如果是引用则将$ret解引用为数组,否则不理会
    猜你喜欢
    • 2016-06-17
    • 1970-01-01
    • 2011-10-11
    • 1970-01-01
    • 2018-02-25
    • 2020-12-09
    • 2019-06-01
    • 1970-01-01
    • 2011-07-26
    相关资源
    最近更新 更多