需要帮助理解这个逐行文件处理器

时间:2011-12-18 16:30:15

标签: perl

我正在尝试使用下载的Perl代码,其中包括用于逐行读取输入文件的以下部分。

但是,我不太明白它是如何运作的

  1. $row[-1]代表什么?可以从-1生成一行

  2. $result{$id}{$group[0]}=$group[1];如何运作?它是否为结果构建了一个二维数组?

  3. $df{$group[0]}++;做了什么?这与C ++中的++相同吗?

  4. my $result =();
    my $df = ();
    
    while (<FILE>)
    {    
       my @row = split;
       my $id = $row[-1];
       for my $i(0 .. $#row - 2)
       {
          my @group = split(/\:/, $row[$i]);
          $result{$id}{$group[0]}=$group[1];
          $df{$group[0]}++;
       }
     }
    

4 个答案:

答案 0 :(得分:5)

以下是该代码的工作方式。

  • 定义$result$df。并且由于一些奇怪的原因,尝试为它们分配一个空列表,即使它没有做任何事情。

    my $result =();
    my $df = ();
    
  • FILE文件句柄中读取一行,并将其放入$_,每行。

    while (<FILE>)
    {
    
  • 在空白处拆分$_,删除第一个元素,如果它是空白的。

      my @row = split;
    
  • $id设置为@row的最后一个元素。

      my $id = $row[-1];
    
  • 循环除@row之外的所有索引,除了最后两个,并将$i设置为索引。如果先前的操作已经到pop结尾的最后一个元素,那么这将更容易编写。我认为它应该是$#row-1而已。

      for my $i(0 .. $#row - 2)
      {
    
  • @row位于$i的{​​{1}}分割元素,:

        my @group = split(/\:/, $row[$i]);
    
  • 索引到%result(不是$result)。

    首先是$id,然后是@group的第一个元素。将其设置为@group的第二个值。

        $result{$id}{$group[0]}=$group[1];
    
  • %df(不是$df)的增量元素,第一个值为@group。如果之前不存在,它最终会将其设置为1

        $df{$group[0]}++;
    
  • for结束while循环。

      }
    }
    

这就是我写它的方式。

use strict;
use warnings;
use autodie;

my $filename = 'filename';
open my $fh, '<', $filename;

my %result;
my %df;

while (<$fh>){
  my @row = split;
  my $id = pop @row;
  pop @row; # I assume this should be removed.
  for my $pair (@row){
    my($key,$value) = split(':', $pair);
    $result{$id}{$key} = $value;
    $df{$key}++;
  }
}

答案 1 :(得分:2)

有时,通过示例最好地解释代码。

给定包含以下行的文件:

AA:BB CC:DD     CC:DD UNIMPORTANT_COL ID

%result哈希看起来像:

(
    ID => {
            AA => 'BB',
            CC => 'DD',
          },
)

%df哈希计算唯一实例的数量:

(
    AA => 1,
    CC => 2,
)

旁边评论

  • $#row@row的最后一个索引,在上面的示例中为4。这意味着可以使用$row[$#row]代替$row[-1]
  • my ( $key, $value ) = split /:/, $group;并使用它们代替$group[0]$group[1]
  • 会更清楚
  • $i变量在这里不是很有用。请考虑使用foreach my $group ( @group[0..$#group-2]) {代替

答案 2 :(得分:1)

  1. $row[-1]代表@row数组的最后一个元素($row[-2]代表之前的那个元素,依此类推)

  2. $result{$id}{$group[0]}=$group[1]使用大量的perl快捷方式,实际上它与$result->{$id}->{$group[0]} = $group[1]相同。

    这意味着以下内容:

    • $result视为对HASH的引用,在该HASH中找到与键$id相关联的元素,如果没有这样的元素,则创建新元素
    • 将该元素视为对HASH的引用,在该HASH中找到与键$group[0]关联的元素,如果没有这样的元素,则创建新元素
    • $group[1]的值分配给该元素

    所以$result是对HASH的HASH的引用。 (详见Perl Data Structures Cookbook

  3. $df{$group[0]}++;会增加$group[0]引用的HASH中键$df的值。与C ++的区别在于,当没有与键关联的值时,该值将被视为0

答案 3 :(得分:0)

  1. 显然,id是行中的最后一列,$row[-1]返回@row数组中的最后一个元素。

  2. $result{$id}{$group[0]}=$group[1]通过将值$group[1]分配给键$id$group[0]

  3. 的组合来构建二维HASH
  4. 增量运算符(++)的工作方式与C ++相同