Как получить доступ к вложенному хэшу массивов в цикле? - PullRequest
0 голосов
/ 14 мая 2018

У меня есть данные в этом формате

a1 1901 4
a1 1902 5
a3 1902 6
a4 1902 7
a4 1903 8
a5 1903 9

Я хочу рассчитать совокупный балл (3-й столбец) для каждого объекта в первом столбце.Поэтому я попытался создать хеш, и мой код выглядит следующим образом:

use strict;
use warnings;

use Data::Dumper;

my $file = shift;
open (DATA, $file);

my %hash;
while ( my $line = <DATA> ) {
  chomp $line;
  my ($protein, $year, $score) = split /\s+/, $line;
  push @{ $hash{$protein}{$year} }, $score;
}

print Dumper \%hash;

close DATA:

Вывод выглядит следующим образом

$VAR1 = {
          'a3' => {
                    '1902' => [
                                5
                              ]
                  },
          'a1' => {
                    '1902' => [
                                6
                              ],
                    '1901' => [
                                4
                              ]
                  },
          'a4' => {
                    '1903' => [
                                8
                              ],
                    '1902' => [
                                7
                              ]
                  },
          'a5' => {
                    '1903' => [
                                9
                              ]
                  }
        };

Теперь я хочу получить доступ к каждой сущности в столбце 1 (a1,a2, a3) и добавьте счет, так что желаемый результат будет примерно таким:

a1 1901 4
a1 1902 9    # 4+5
a3 1902 6
a4 1902 7
a4 1903 16   # 7+9
a5 1903 9

Но я не могу придумать, как получить доступ к значениям созданного хэша в цикле, чтобыдобавить значения?

Ответы [ 2 ]

0 голосов
/ 14 мая 2018

Если данные всегда сортируются так, как вы их отображаете, то вы можете обрабатывать данные так, как считываете их из файла:

while ( <DATA> ) {
    my ($protein, $year, $score) = split;

    $total = 0 unless $protein eq $current;
    $total += $score;

    print "$protein $year $total\n";

    $current = $protein;
}

output

a1 1901 4
a1 1902 9
a3 1902 6
a4 1902 7
a4 1903 15
a5 1903 9
0 голосов
/ 14 мая 2018

Я думаю,

a4 1903 16   # Sum of a4 1902 and a5 1903

должно быть

a4 1903 15   # Sum of a4 1902 and a4 1903

Если это так,

my %scores_by_protein_and_year;
while (<DATA>) {
   my ($protein, $year, $score) = split;
   $scores_by_protein_and_year{$protein}{$year} = $score;
}

for my $protein (keys(%scores_by_protein_and_year)) {
   my $scores_by_year = $scores_by_protein_and_year{$protein};
   my $score = 0;
   for my $year (sort { $a <=> $b } keys(%$scores_by_year)) {
      $score += $scores_by_year->{$year};
      say "$protein $year $score";
   }
}

Это работает, даже если данные не сгруппированы / отсортированы.

...