2

我是 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 ;。原作者想在这里做什么?

4

6 回答 6

3

这段代码%summary使用%trades. 每笔交易都是一个包含多个字段的数组,这些字段在循环中解包。ie$sym是当前交易的第一个数组字段的值,$qty最后一个字段

$summary{$sym}访问哈希$sym中的字段。然后访问该字段中%summary命名的条目。如果该字段不存在,则创建它。如果不包含 hashref,则会在此处创建一个,因此一切正常。(技术术语:自动复活)$type$summary{$sym}$summary{$sym}

$var += $x添加$x$var,因此在循环结束后保存所有具有相同和$summary{$sym}{$type}的值的总和。$qty$sym$type

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

于 2013-06-13T14:17:29.147 回答
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 中,您可以通过在引用前面放置正确的符号来取消引用。例如:

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 关于参考的简短教程

于 2013-06-13T15:35:59.647 回答
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];).
于 2013-06-14T08:07:44.713 回答
0

$summary{$sym}{$type} is a scalar inside a hashref inside a hash.

+= is an operator that takes the left hand side, adds the right hand side to it, then assigns the result back to the left hand side.

$qty is the value to add to the previously stored value.

于 2013-06-13T14:12:25.530 回答
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

通过这种方式,您实际上可以看到哈希内部的内容,甚至哈希的哈希。

于 2013-06-14T12:45:43.627 回答
-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);
于 2013-06-13T14:21:43.433 回答