无法理解以下Perl语法

时间:2013-06-13 14:07:38

标签: perl

我是第一个使用Perl的计时器,我必须对Perl脚本进行更改,并且我遇到了以下内容:

my %summary ;
for my $id ( keys %trades ) {
    my ( $sym, $isin, $side, $type, $usrOrdrNum, $qty ) = @{$trades{$id}} ;
    $type = "$side $type" ;
    $summary{$sym}{$type} += $qty ;
    $summary{$sym}{'ISIN'} = $isin  ;
}

我不理解的部分是$summary{$sym}{$type} += $qty ;。原作者试图在这做什么?

6 个答案:

答案 0 :(得分:3)

这段代码使用%summary中的数据摘要填充%trades哈希。每个交易都是一个包含多个字段的数组,这些字段在循环内解压缩。即$sym是当前交易的第一个数组字段的值,$qty最后一个字段

$summary{$sym}访问$sym哈希中的%summary字段。然后访问$type字段中名为$summary{$sym}的条目。如果该字段不存在,则创建该字段。如果$summary{$sym}没有hashref,那么就会在那里创建一个,所以一切都正常工作。 (技术术语:autovivification)

$var += $x$x添加到$var,因此$summary{$sym}{$type}包含所有$qty值的总和,其中$sym和{{1}循环结束后。

$type字段将保留名称为$summary{$sym}{ISIN}的最后一笔交易的$isin值(我怀疑它们对所有此类交易都是相同的)。

答案 1 :(得分:1)

Perl有三种内置的不同数据类型:

  • 标量(如$foo)。
  • 数组(如@foo)。
  • 哈希(如%foo)。

问题是每个都处理单个数据位。当然,列表和散列中可能有很多项,但它们有很多单个数据位

假设我想跟踪人。人们有名字,姓氏,电话等。让我们定义一个人:

my %person;

$person{FIRST_NAME} = "Bob";
$person{LAST_NAME} = "Smith";
$person{PHONE_NUMBER} = "555-1234";

好的,现在我需要存放另一个人。我是否创建另一个哈希?如果我可以拥有一个散列数组,每个散列代表一个人?

Perl允许您通过对哈希值引用来执行此操作:

my @list;
push @list, \%person;

\%person是我对包含哈希值的内存位置的引用。 $list[0]指向该内存位置,并允许我通过解除引用访问该人。

现在,我的数组包含了我的人物。我可以创建第二个:

$person{FIRST_NAME} = "Susan";
$person{LAST_NAME} = "Brown";
$person{PHONE_NUMBER} = "555-9876";
push @list, \%person.

好的,我如何引用我的。在Perl中,通过在参考前面放置正确的sigil来取消引用。例如:

my $person_ref = @list[0];  #Reference to Bob's hash
my %person = %{person_ref}; #Dereference to Bob's hash. %person is now Bob.

有些事情,我正在将大量数据从一个变量移动到另一个变量,而我并没有真正使用这些变量。让我们消除变量,或至少消除它们的名称:

my @list;
push @list, {};   #Anonymous hash in my list

$list[0]仍然指向对哈希的引用,但我从来没有给该哈希命名。现在,我如何将Bob的信息放入其中?

如果$list[0]是对哈希的引用,我可以通过在其周围放置%{...}来取消引用它!

%person = %{ $list[0] };  #Person is an empty hash, but you get the idea

让我们填写那个哈希!

${ $list[0] }{FIRST_NAME} = "Bob";
${ $list[0] }{LAST_NAME} = "Smith";
${ $list[0] }{PHONE_NUMBER} = "555-1234";

这很容易阅读......

幸运的是,Perl提供了一些语法甜味剂。这是一样的:

$list[0]->{FIRST_NAME} = "Bob";
$list[0]->{LAST_NAME} = "Smith";
$list[0]->{PHONE_NUMBER} = "555-1234";

->运算符指向您正在执行的取消引用。

此外,在某些情况下,我不需要{...}花括号。把它想象成数学运算,其中有一个优先顺序:

(3 x 4)+(5 x 8)

与:

相同

3 x 4 + 5 x 8

一,我指定操作的顺序,另一个我不指定:

将原始名称添加到存储在列表中的哈希引用中:

${ $list[0] }{FIRST_NAME} = "Bob";
${ $list[0] }{LAST_NAME} = "Smith";
${ $list[0] }{PHONE_NUMBER} = "555-1234";

可以改写为:

$list[0]{FIRST_NAME} = "Bob";
$list[0]{LAST_NAME} = "Smith";
$list[0]{PHONE_NUMBER} = "555-1234";

(我不必先做push @list, {};。我只是想强调这是对哈希的引用。

因此:

$trades{$id}

是对数据数组的引用。

以这种方式思考:

my @list = qw(a bunch of data);
$trades{$id} = \@list;

要取消引用列表的引用,我这样做:

@ {交易{$ ID}}

请参阅Mark's Short Tutorial About References

答案 2 :(得分:0)

$summary{$sym}{$type}是哈希内部hashref内的标量。

+=是一个左侧的操作员,右侧添加,然后将结果分配回左侧。

$qty是要添加到先前存储的值的值。

答案 3 :(得分:0)

$summary{$sym}{$type} += $qty ;  #is the same as 
#$summary{$sym}{$type} = $summary{$sym}{$type} + $qty; 
#This line calculates total of the values from the hash %trades ($trades{$id}[5];).

答案 4 :(得分:0)

如果您是新手,在Perl中查看类型的最佳方法是使用perl调试器选项。 您可以将脚本运行为:

perl -d <scriptname>

然后在调试器中使用(你会看到类似的东西)

  DB<1>

键入以下内容以转到要调试的代码:

  DB<1> c <linenumber>

然后您可以使用x来查看变量,如:

  DB<2>x %trades
  DB<3>x $trades{$id}
  DB<4>print Dumper \%trades

通过这种方式,您可以实际查看哈希中的内容甚至哈希哈希值。

答案 5 :(得分:-2)

它计算前三个字段的每个值组合的最后一个字段中所有值的总和。

如果哈希是一个SQL表而不是(为什么不这样 - 像DBD::CSV这样的东西可以在这里派上用场)id, sym, isin, side, type, usrOrdrNum, qty,代码将转换为类似

的内容
SELECT sym, CONCAT(side,' ',type) AS type, SUM(qty), isin
FROM trades
GROUP BY sym, CONCAT(side,' ',type);