我是第一个使用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 ;
。原作者试图在这做什么?
答案 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}}
答案 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);