【问题标题】:Cannot understand the following Perl syntax无法理解以下 Perl 语法
【发布时间】:2013-06-14 20:45:43
【问题描述】:

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

【问题讨论】:

  • $summary{$sym}{$type}$summary{$sym}->{$type} 相同
  • 当您在+= 行之前和之后执行print %summary; 时,可能会更清楚。
  • @ott-- 没有帮助,这会给sym1ARRAY(0xC0FFEE123)sym2ARRAY(0xDEADBEEF) 等提供更好的use Data::Dumper; ...; print Dumper \%summaryuse Data::Dump; ...; dd \%summary 来查看嵌套数据结构。
  • 你用什么perl? perl -e '%coins = ("Quarter", 25, "Dime", 10, "Nickel", 5); print %coins;'Nickel5Dime10Quarter25
  • @ott--,OP 有一个嵌套散列。

标签: perl


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

    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;
    

    为了取消对列表的引用,我这样做:

    @{trades{$id}}

    Mark's Short Tutorial About References

    【讨论】:

      【解决方案3】:

      $summary{$sym}{$type} 是散列内的 hashref 内的标量。

      += 是一个运算符,它取左侧,将右侧添加到它,然后将结果分配回左侧。

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

      【讨论】:

        【解决方案4】:
        $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];).
        

        【讨论】:

          【解决方案5】:

          如果您是新手,在 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
          

          这样你就可以真正看到hash里面有什么,甚至hash的hash。

          【讨论】:

            【解决方案6】:

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

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

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

            【讨论】:

            • 直到现在才投反对票 ;-) 您的回答提供了将代码翻译成声明性语言。但是,这需要 SQL 知识。它引入了庞大的 DBI 框架来处理 OP 的简单代码可以直接执行的多级间接操作。它忽略了 OP 具​​有数据结构,而不是 CSV 文件。最重要的是,您不是在解释代码和语法,而是提供替代解决方案。可以想象,对于 OP 理解他给出的 Perl 代码,您的回答可能更令人困惑而不是帮助。
            • 这个网站的想法是不同的答案可以针对同一个问题给出。
            猜你喜欢
            • 1970-01-01
            • 2017-11-23
            • 1970-01-01
            • 1970-01-01
            • 2014-01-21
            • 1970-01-01
            • 2021-10-14
            • 2011-09-06
            • 1970-01-01
            相关资源
            最近更新 更多