2011-12-23 1 views
2

У меня есть следующие структуры хэшированного $chainStorage{$R1}{$S1}{$C1} = \@A1петли через сложную структуру хэш

$chainStorage = { 
     'ACB' => { 
       'E' => {'06' => [100, 200, 95]} 
       'B' => {'23' => [20, 1000, 05, 30]} 
     }, 
     'AFG' => { 
       'C' => { '24' => [18, 23, 2300, 3456]} 
     }, 
     'HJK' => { 
       'A' => {'12' => [24, 25, 3200, 5668]} 
       'D' => {'15' => [168]} 
     } 
}; 

Например, ACB соответствует двум массивам, [100, 200, 95] и [20, 1000, 05, 30] в то время как E соответствует только [100, 200, 95].

Прямо сейчас мне нужно добавить все элементы в массиве, соответствующие клавише первого уровня, например ACB.

Другими словами, в другой хэш-структуры, я хочу ACB соответствует

100+200+95 + 20+1000+05+30 = 1450 

Как реализовать эту функцию через $chainStorage?

ответ

7

Вы могли бы сделать что-то вроде:

#!/usr/bin/perl 
use strict; 
use warnings; 
use Data::Dump qw(dump); 

my $chainStorage = { 
     'ACB' => { 
       'E' => {'06' => [100, 200, 95]}, 
       'B' => {'23' => [20, 1000, 05, 30]} 
     }, 
     'AFG' => { 
       'C' => { '24' => [18, 23, 2300, 3456]} 
     }, 
     'HJK' => { 
       'A' => {'12' => [24, 25, 3200, 5668]}, 
       'D' => {'15' => [168]} 
     } 
}; 


while (my($k,$v) = each %$chainStorage) { 
    my $sum = 0; 
    while (my($k2,$v2) = each%$v) { 
     while (my($k3,$v3) = each %$v2) { 
      foreach (@$v3) { 
       $sum += $_; 
      } 
     } 
    } 
    $chainStorage->{$k} = $sum; 
} 
dump$chainStorage; 

выход:

{ ACB => 1450, AFG => 5797, HJK => 9085 } 
0

Вы могли бы написать стандартный хвост рекурсивной fold (+) как рутина, которая обеспечивает широту первый спуск произвольной иерархии Perl структуры данных, суммируя все встреченные числовые скаляры. Пример:

use Switch; 

sub deep_fold_sum { 
     my $v=0; my @l=(); 
     while (shift) { switch (ref) { 
       case '' { $v += $_; } 
       case 'SCALAR' { $v += $$_; } 
       case 'ARRAY' { push(@l, @$_); } 
       case 'HASH' { push(@l, values %$_); } 
     } } 
     return $v unless @l; 
     return deep_fold_sum($v, @l); 
} 

Я не тестировал этот код, но любые ошибки должны быть легко исправить. Если вы хотите надлежащего хвостовую рекурсию, возможно, потребуется заменить окончательную линию возврата по:

 @_ = ($v, @l); 
     goto &deep_fold_sum; 

Наконец, вы можете tie объект, который использует эту функцию, чтобы обеспечить нужный интерфейс хэш-как динамически.

+0

Вы можете, очевидно, отвлечь функцию накопления '+ =', если хотите, чтобы ее легко заменить словами 'join',' .' и т. Д. –

+0

Если ваша структура данных огромная, но неглубокая, то вы можете найти глубину первый поиск более эффективен. –