【问题标题】:Clarification on hash++关于哈希++的说明
【发布时间】:2011-06-27 16:33:30
【问题描述】:

我正在阅读 Damian Conway 的“Perl 最佳实践”,发现以下代码片段:

$have_reconsidered{lc($name)}++;

我试图弄清楚散列在这里发生了什么。我知道++ 在数字上下文中加一,但它对哈希有什么作用?

来自perlop documentation

undef 始终被视为数字, 特别是更改为0 在递增之前(这样一 undef 值的后增量将 返回 0 而不是 undef)。这 自减运算符不是 神奇。

那么在上面的示例中,键 lc($name) 的值是否被初始化为 0,然后由 ++ 递增为 1

一般来说,我在哪里可以找到更多关于+++= 等...的行为?

【问题讨论】:

  • 声明中,$hash{key}++,++是对哈希的元素进行操作,而不是哈希本身。 %hash++ 是不允许的。唯一不太明显的一点是,如果$hash{key} 不存在,则将其实例化为 0 然后递增。 += 会发生这种情况,.= 创建一个空字符串并附加到它。

标签: perl operators


【解决方案1】:

%have_reconsidered 是你的哈希值。 $name 是一个字符串。 lc($name) 返回小写字符串。 $hash{$key} 将返回哈希值%hash 中的标量值,该值存储在密钥$key 中。所以:

// get scalar value from hash at key lc($name) and post-increment it
$have_reconsidered(lc($name)}++;

所以,你所做的就是在给定索引处增加哈希值(即lc($name)

测试用例:

#!/bin/env perl
my %hash = ( 'a' => '2' );
my $name = 'A';
print $hash{lc($name)}++; // prints 2 (incremented after statement)
print $hash{lc($name)};   // prints 3
print ++$hash{lc($name)}; // prints 4 (incremented before statement)

【讨论】:

  • @knittl:我明白这一点,但是在代码出现的上下文中(我知道我的问题中没有包含),键 lc($name) 的值似乎没有定义或以前解决过。
  • @YGomez:然后您应该在问题中包含原始代码。 $name 的值是多少?
  • @knittl:name 的值无关紧要。更多的是$hash{lc($name)} 的价值。我想我从你的回复中理解了。如果定义了$hash{lc($name)} 的值,那么它将增加1。否则它会被初始化为1,是吗?
  • @YGomez:否则它将被初始化为 0,然后递增 1。您可以为哈希添加新键,这就是它的美妙之处。如果它们以前不存在,perl 甚至会即时创建所有变量。你可以use strict来避免这样的错误
  • 这不是复杂性,而是两个简单功能的组合...++ 并在可修改的上下文中使用哈希元素。您不会找到遍历不同功能的所有可能组合的文档。
【解决方案2】:

哈希值是标量,所以$have_reconsidered{lc($name)}++; 增加了标量 $have_reconsidered{lc($name)}。如果该标量之前未定义或不存在,++ 会将其设置为 1。

这段代码的目标可能是删除重复项。

>perl -E"++$seen{$_} for qw( a a a b c a d ); say keys %seen;"
cabd

我更喜欢类似但不同的方法,因为它保留了顺序。

>perl -E"say grep !$seen{$_}++, qw( a a a b c a d );"
abcd

【讨论】:

  • 来自 perlop:“请注意,就像在 C 中一样,Perl 没有定义变量何时递增或递减”您能否解释一下您的两个示例代码之间的区别?
  • @YGomez,首先,从哈希中提取结果。在后者中,结果是对原始列表的过滤。
【解决方案3】:

$have_reconsidered{lc($name)} 是属于键 lc($name) 的哈希 %have_reconsidered 的值。这个值绝对可以是数字,但即使它是一个字符串,它仍然可以自动递增(参见http://perldoc.perl.org/perlop.html#Auto-increment-and-Auto-decrement)。

【讨论】:

    猜你喜欢
    • 2017-10-30
    • 2016-02-19
    • 1970-01-01
    • 2019-08-29
    • 2019-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多