Арифметические операции между двумя хеш-массивами

У меня есть хеш-массив с YAML, который был взят из команды Linux. У меня есть другой хеш-массив с тем же набором YAML, но с другими значениями, той же командой, которая была запущена позже.

Eg.

content.none: 
  bytes:  31046
content.image.gif: 
  bytes:  0

а также

content.none: 
  bytes:  31050
content.image.gif: 
  bytes:  0

Теперь я ищу математическую операцию между значениями. Я ищу выход

content.none: 
  bytes:  4
content.image.gif: 
  bytes:  0

который является результатом математики между соответствующими значениями в хеше.

Я пробовал повторять и делать diff, но это похоже на кумулятивный результат.

%host_stat_new=New stats
 %host_stat_old=Old stats (taken from stats.yml, which contains old data)
while (true){
open my $FH1, ">stats.yml" or die "cannot write to stat file because $!\n";
foreach my $line4 (keys %host_stat_new){
        print $FH1 "$line4:\n";
        foreach my $line5 (keys %{$host_stat_new{$line4}}) {
                print $FH1 "  $line5: \n";
                foreach my $line6 (keys %{$host_stat_new{$line4}{$line5}}){
                my $diff1 = $host_stat_new{$line4}{$line5}{$line6};
                my $diff2 = $host_stat_old{$line4}{$line5}{$line6};


$math=$diff1-$diff2;
#$host_stat1{$line4}{$line5}{$line6} = $math;
$host_stat_new{$line4}{$line5}{$line6} = $math;
                    print $FH1 "    $line6:  $host_stat_new{$line4}{$line5}{$line6}\n";
                    }
            }


    }
}

Что я здесь делаю неправильно? Есть ли какой-нибудь модуль, который может это сделать?


person nohup    schedule 19.03.2014    source источник
comment
И что происходит? Какой результат ожидается, какой результат дан? Не могли бы вы использовать Data::Dumper для %host_stat_old и new, чтобы мы могли видеть, как заполняется этот хэш? Вы use strict и use warnings?   -  person DeVadder    schedule 19.03.2014
comment
Вывод в первый раз идет как разность, но со второй итерации он появляется как кумулятивный. Да, Strict и Warnings используются.   -  person nohup    schedule 19.03.2014


Ответы (1)


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

use YAML;

use strict;
use warnings;

my $str1 = <<YAML_STRING1;
content.none: 
  bytes:  31046
content.image.gif: 
  bytes:  0
YAML_STRING1

my $str2 = <<YAML_STRING2;
content.none: 
  bytes:  31050
content.image.gif: 
  bytes:  0
YAML_STRING2

my $data1 = Load($str1);
my $data2 = Load($str2);

my $diff = diff_recurse($data2, $data1);

print Dump($diff);

sub diff_recurse {
    my ($str1, $str2) = @_;

    my $diff;

    if ('HASH' eq ref $str1) {
        $diff = {};
        for my $key (keys %$str1) {
            $diff->{$key} = diff_recurse($str1->{$key}, $str2->{$key});
        }

    } elsif ('ARRAY' eq ref $str1) {
        $diff = [];
        for my $i (0..$#$str1) {
            $diff->[$i] = diff_recurse($str1->[$i], $str2->[$i]);
        }

    } elsif (my $unknown = ref $str1) {
        die "Unknown type $unknown\n";

    } elsif ($str1 =~ /^[\d\.]+$/) {
        $diff = $str1 - $str2;
    } else {
        $diff = $str1;
    }

    return $diff;
}

Выходы

---
content.image.gif:
  bytes: 0
content.none:
  bytes: 4
person Miller    schedule 19.03.2014
comment
Имеет смысл. Спасибо Миллер. - person nohup; 19.03.2014