【问题标题】:Odd number of elements in hash assignment with default具有默认值的哈希分配中的奇数个元素
【发布时间】:2016-09-23 22:32:28
【问题描述】:

问候亲爱的社区。​​p>

我正在尝试在 perl 中创建一个sub,它接受一个散列和一个默认为零的调试标志。但是我不断收到此错误Odd number of elements in hash assignment。如果我不使用调试标志,它似乎可以工作。

感谢大家的帮助。

代码:

#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
use POSIX qw(strftime);


#
#file2hash : read the file in k<file_name> e.g.=kconfig &  kmem  into hash table
#

sub file2hash {
    my ($file) = @_;

open(my $data, '<', $file) or die "Could not open '$file' $!\n";

my %HoH;
my $key;
my $value;
my $who;
my $rec;
my $field;

#while ( my $line = <$data>) {
while ( <$data>) {
    #print $line;
    next unless (s/^(.*?):\s*//); # / turn off editor coloring
    $who = $1;
    #print $who;
    $rec = {};
    $HoH{$who} = $rec;
    for $field ( split ) {
        ($key, $value) = split /=/, $field;
        $rec->{$key} = $value;
    }
}

    return %HoH;

}
#
#end file2hash
#


#
#print out hash table in k<file_name> format
#
sub hash2print{
    (my %HoH,my $debug) = @_;
    #my ($debug)=@_||0;
    #my %HoH = shift;
    #my $debug = shift || 0;

    my $family;
    my $role;

    for $family ( keys %HoH ) {
        #print "$family\n";
        for $role ( keys %{ $HoH{$family} } ) {
             if ($debug){
                print "family:$family\n";
                print "role: $role\n";
             }
             print "$role=$HoH{$family}{$role}";

        }
        print "\n";
    }
}
#
#end hash2print
#

sub dispatch{

        my $inc= shift;
        my $config_f = shift || "kconfig";
        my $memory_f = shift || "kmem";

        my %h2=&file2hash($config_f);
        my %m2=file2hash($memory_f);

        my $today=&getDate();

        print "$today\n";
        print "$inc\n";
        my $inc_cnt = $m2{$today}{$inc} || -999999999;
        print "$inc_cnt\n";

        #my %config = shift;
        #my %mem = shift;
        #my $event = shift;
        #print $m2{$inc}{$today};
}

sub getDate{
my $date = strftime "%m/%d/%Y", localtime;  # "
#print $date;
return $date;
}

my %h2=&file2hash("kconfig");
my %m2=&file2hash("kmem");
&hash2print(%h2,1);
&hash2print(%m2,1);
#print &getDate();
#my $xcnt= &dispatch("event_c3_z2");
#&dispatch("event_c3_z2");
#print $xcnt;

测试文件1:

event_a1_x1: email1=ackee0000@gmail.com email2=kym018@gmail.com email1_cnt=6
event_a1_x2: email1=ackee0000@gmail.com email2=kym018@gmail.com email1_cnt=5 
event_b2_y1: email1=ackee0000@gmail.com email2=kym018@gmail.com email1_cnt=4 
event_b2_y2: email1=ackee0000@gmail.com email2=kym018@gmail.com email1_cnt=3 
event_c3_z1: email1=ackee0000@gmail.com email2=kym018@gmail.com email1_cnt=2 
event_c3_z2: email1=ackee0000@gmail.com email2=kym018@gmail.com email1_cnt=1

测试文件2:

201609230012: event_a1_x1=6
201609230744: event_a1_x2=5
201609230844: event_b2_y1=4
201609230342: event_b2_y2=3
201609230245: event_c3_z1=2
201609230100: event_c3_z2=1

【问题讨论】:

  • 我编辑了您的帖子以关闭错误的(红色)颜色。它经常发生在正则表达式等之后,编辑器被斜杠等弄糊涂了,然后在那之后将所有东西都涂成红色。大多数情况下添加评论# / 可以解决问题,但有时您需要在评论中尝试不同的字符。如果您不喜欢这个,请“回滚”我的编辑 - 转到我的用户名上方的“已编辑(时间)”链接,您会看到修订。

标签: perl


【解决方案1】:

参数作为一个平面列表传递给函数。另一方面,可以为哈希分配一个列表%h = qw(a b),其中连续元素形成键值对,$h{a}'b'。因此,当哈希是函数中接收参数的第一个变量时,它会收集所有参数。这是一个recent post,关于函数如何返回,同样的故事也适用。

因此,所有内容都分配给哈希,其余的标量也是如此。因此,哈希得到的元素比预期的多一个,最终得到奇数个元素。

一种解决方案——在这种情况下,仅通过引用传递哈希,如Inferno 的回答中所示

sub hash2print{
    my ($rHoH, $debug) = @_;
    my %HoH = %$rHoH;
    # ...
}
hash2print(\%h2, 1);

原则上,通过引用传递列表是个好主意,除非它们很短。

一般来说,你可以先传递标量,然后传递哈希

sub hash2print{
    my ($value, %HoH) = @_;
    # ...
}
hash2print(1, %h2);

但在您的情况下,这不会发生,因为 $debug 是可选的,如果我们在调用函数时将其省略,哈希的第一个键将在 $value 中结束。

一些其他的cmets

  • 除非有不可协商的原因,否则不要使用全局变量。小范围声明。

  • 不用$rec = {};,直接声明my $rec;即可。

  • 一般情况下,不要将&amp;放在函数调用前面,而只使用file2hash(...)

【讨论】:

  • @ikegami 非常感谢您的修复。
【解决方案2】:

您希望将散列值按值传递给子例程,这会产生问题。尝试通过引用传递您的哈希%h2(注意% 之前的\):

&hash2print(\%h2, 1);

然后在您的子hash2print 中,您可以通过以下方式取回哈希:

sub hash2print {
    (my $hashref, my $debug) = @_;
    my %HoH = %$hashref; # dereference $hashref to get back the hash
    ...

如果您不了解参考文献here 背后的概念,可以阅读更多关于它们的信息。

【讨论】:

    猜你喜欢
    • 2021-11-01
    • 1970-01-01
    • 2016-04-15
    • 2012-07-20
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多