【问题标题】:Is this the correct way to build a Perl hash that utilizes arrays?这是构建利用数组的 Perl 哈希的正确方法吗?
【发布时间】:2011-01-31 02:57:16
【问题描述】:

这是我第一次以这种方式操作哈希和数组——而且它正在工作。基本上,对于每个键,我都想记录多个值,然后以“key --> value --> value --> val...”的形式打印出来

我的代码如下。我很惊讶它的工作原理,所以担心它“错误地”工作。这是完成这项任务的正确方法,还是有更有效或更合适的方法?

while ($source =~ m/(regex)/g) { #Get all key names from source
    $listkey = $1; #Set current list key to the current regex result.
    $list{$listkey} = ++$i unless $list{$listkey}; #Add the key to the hash unless it already exists.
    $list{$listkey} = [] unless exists $list{$listkey}; #Add an array for the hash unless the hash already exists.
    while ($loopcount==0) {
            if ($ifcount==0) {
                    $listvalue=result_of_some_function_using_list_key; #Get the first list value by using the list key.
                    $ifcount++; #Increment so we only get the first list value once.
            } else {
                    $listvalue=result_of_some_function_using_list_value; #Update the list value by using the last list value.
            }
            if ($listvalue) { #If the function returned a value...
                    push @{$list{$listkey}}, $listvalue; #...then add the value to the hash array for the key.
            } else { #There are no more values and we need a new key.
                    $listkey=0; #Reset variable.
                    $listvalue=0; #Reset variable.
                    $loopcount++; #Increment loop counter to exit loop.
            }
    }
$ifcount=0; #Reset count variable so the next listvalue can be generated from the new key.
    $loopcount=0; #Reset count variable so another loop can begin for a new key.
}
foreach $listkey (keys %list) { #For each key in the hash.
    print "$listkey --> "; #Print the key.
    @values = @{$list{$listkey}}; #Reference the arrays of the hash.
    print join ' --> ', @values; #Print the values.
    print "\n"; #Print new line.
}

【问题讨论】:

  • 你真的应该在use strict; use warnings;模式
  • 哎呀,这产生了一个邪恶的警告列表。我将不得不通过它们。
  • 我希望真实的代码没有这么多的cmets。
  • 我很惊讶没有人向您指出 Data Structures Cookbook,又名 perldoc perldsc - perldoc.perl.org/perldsc.html 许多示例。
  • 不,真正的代码没有这么多的cmets。 :) 谢谢你的食谱链接!

标签: perl hash arrays


【解决方案1】:

以下代码与您的代码相同,没有不必要的步骤。

while ($source =~ m/(regex)/g) { # Get all key names from source
    $listkey = $1;            # Grab current regex result.
    $listvalue = result_of_some_function_using_list_key;
    while ($listvalue) {
        push @{$list{$listkey}}, $listvalue; 
        $listvalue = result_of_some_function_using_list_value;
    }
    $listkey = 0;                # Reset variable.
    $domain = 0;                 # Reset variable.
}   

但是,正如其他人所评论的那样,在大多数情况下应避免使用全局变量。相反,列表键和列表值应在词法范围内使用my(),生成列表值的函数应采用一个或多个参数(域、列表键和/或列表值)作为输入。

线条

$list{$listkey} = ++$i unless $list{$listkey};
$list{$listkey} = [] unless exists $list{$listkey};

在您的原始代码中不需要,使用push @{ $list{$key} }, $value 来初始化条目就足够了。

【讨论】:

  • 谢谢,经过简短的解释,我对哪里出错有了更好的理解。
【解决方案2】:

上面的代码有很多不必要的步骤。 Perl 是一种表达能力很强的语言,可以非常简单地表达这样的逻辑:

# uncomment for some sample data
# sub function {"@_" !~ /^\[{3}/ and "[@_]"}
# my $source = 'one two three';

my %list;
while ($source =~ m/(\S+)/g) {
    my $key   = $1;
    my $value = function($key);

    while ($value) {
        push @{ $list{$key} }, $value;
        $value = function($value)
    }
}

for my $key (keys %list) {
    print join(' --> ' => $key, @{$list{$key}}), "\n";
}

【讨论】:

  • 同意。通常,在 Perl 中,您应该只看到循环索引(for ($i = 0... C 风格的循环)或计数器,在您实际需要对这些值执行某些操作的情况下。计数器和索引通常也是难以发现的错误的良好来源
【解决方案3】:

不!如果这行得通,那肯定是“错误地”。但也很明显,这不是您的真实代码,并且您在将其“翻译”为示例时添加了更多错误,因此很难准确判断其意图是什么,但从程序的框架来看,它看起来应该是这样的:

my %result;

while ($source =~ m/(regex)/g) {
  my $key = $1;
  my $value = mangle($key);
  while ($value) {
    push @{ $results{$key} }, $value;
    $value = frob($value);
  }
}

仅此而已。您初始化哈希的尝试并没有按照您的想法进行(并且没有必要),您编写的 while 循环根本不是一个好主意,所有全局变量也不是。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-24
    • 2014-02-21
    • 2011-12-15
    • 2015-03-26
    • 1970-01-01
    • 2010-09-16
    • 2010-12-17
    • 2010-12-07
    相关资源
    最近更新 更多