【问题标题】:Sum values in second column in a text file在文本文件的第二列中求和值
【发布时间】:2019-10-23 00:21:51
【问题描述】:

我有一个格式如下的文本文件:

1 4730 1031782 init
4 0 6 events
2190 450 0 top
21413 5928 1 sshd
22355 1970 2009 find 

我需要对第二列数据求和并将该值返回给用户。

我当前尝试从文本文件中读取数据,如下所示:

sub read_file{
  my $data_failed = 1;
  my $file = 'task_file';
  if (-z $file){print "No tasks found\n";}
  if(open (INFILE, "task_file" || die "$!\n")){
    my @COLUMNS = qw( memory cpu program );
    my %sort_strings = ( program => sub { $a cmp $b } );

    my (%process_details, %sort);

    while (<INFILE>) {
      $data_failed = 0;
      my ($process_id, $memory_size, $cpu_time, $program_name) = split;
      $process_details{$process_id} = { memory  => $memory_size,
                                        cpu     => $cpu_time,
                                        program => $program_name };
      undef $sort{memory}{$memory_size}{$process_id};
      undef $sort{cpu}{$cpu_time}{$process_id};
      undef $sort{program}{$program_name}{$process_id};
    }

    for my $column ($COLUMNS[2]) {
      my $cmp = $sort_strings{$column} || sub { $a <=> $b };
      for my $value (sort $cmp keys %{ $sort{$column} }
      ) {
          my @pids = keys %{ $sort{$column}{$value} };
          say join ' ', $_, @{ $process_details{$_} }{@COLUMNS}
              for @pids;
      }
  }
  if($total_memory_size == 1){
    sum_memory_size();
  }
} else { print "No tasks found"}
}

我尝试对这些值求和:

sub sum_memory_size{
  my @do_sum = qw(memory_size);

my $column;
my $value;

for $column (keys %{ $sort{$column}{$value} }) {
    my $found;
    my $sum = 0;
    for $value (@do_sum) {
        next unless exists $sort{$column}{$value};
        $sum += $hash{$column}{$value};
        delete $hash{$column}{$value};
        $found = 1;
    }
    $sort{$column}{somename} = $sum if $found;
}

print $sum;
}

【问题讨论】:

  • 到目前为止你尝试了什么?
  • @Chris 编辑显示我的尝试
  • 不要将DATA 用于真正的文件句柄,它是一个特殊的句柄(参见perldata)。
  • 好的,我现在正在使用 INFILE
  • 最好使用词法文件句柄而不是裸词句柄。

标签: perl multiple-columns text-processing


【解决方案1】:

使用sum 形式List::Util

use List::Util qw{ sum };

# ...

my $memory_sum = sum(map $_->{memory}, values %process_details);

【讨论】:

  • 很遗憾,我无法使用任何非核心功能,有没有办法使用 + 运算符来做到这一点?
  • @DavideLorino List::Util 自 Perl 5.7.3 以来一直是核心 :)
  • @DavideLorino sum 函数(可从任何版本的 List::Util 中获得)可以通过加法运算符和循环轻松复制:my $memory_sum = 0; $memory_sum += $_-&gt;{memory} for values %process_details;
【解决方案2】:

这个问题描述了一个简单的任务,它似乎是一个更大问题的一部分。简单任务的一个答案是:

perl -ne '@fields=split; $sum+=$fields[1]; END { print "$sum\n" }' foo.txt

对于每一行 (-ne),将其拆分并将第二个值 ($fields[1]) 添加到正在运行的 $sum。然后,在处理完所有行 (END) 后,打印总和。我从程序中得到13078,这也是我从上面输入的计算器中得到的:) (4730 + 0 + 450 + 5928 + 1970)。

【讨论】:

  • 谢谢,如何在不使用命令行参数的情况下将这种方法集成到脚本中?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-02
  • 1970-01-01
相关资源
最近更新 更多