debiandude has asked for the wisdom of the Perl Monks concerning the following question:

I have a hash of an array. For example:
my %hash = ( one => [1,2,4], two => [5,7,9], );
What I would like to be able to easily do is add an array of numbers of to say $hash{one}. As example example, in pseudocode:
$hash{one} += [7,8,11];
So that, $hash{one} now has the following values: 8, 10, 15. Is there an easy way to do this, or must I loop though the individual elements?

Thanks.

Replies are listed 'Best First'.
Re: Add Array values
by davido (Cardinal) on Dec 29, 2004 at 20:37 UTC

    What you're finding is that mathematical operators are not overloaded to work on sets. You need something like this:

    use strict; use warnings; use Data::Dumper; my %hash = ( one => [ 1, 2, 4 ], two => [ 5, 7, 9 ] ); my @add = ( 7, 8, 15 ); $hash{one}->[$_] += $add[$_] foreach 0 .. $#add; print Dumper \%hash;

    Dave

      Thanks very much.
Re: Add Array values
by dragonchild (Archbishop) on Dec 29, 2004 at 20:39 UTC
    You have to add them in a loop. However, there are ways to help you with that. If you wanted to do it by hand, you could say
    my $arr = [7,8,11]; $hash{one}[$_] += $arr->[$_] for 0 .. $#{$hash{one}};
    But, that's ... ugly. A better way would be to use tye's Algorithm::Loops as so
    use Algorithm::Loops qw( MapCarE ); @{$hash{one}} = MapCarE { $_[0] + $_[1] } $hash{one}, [7,8,11];
    The nice thing about this is that you can add more arrays to the end, update sub a little, and you're good. :-)

    Being right, does not endow the right to be rude; politeness costs nothing.
    Being unknowing, is not the same as being stupid.
    Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
    Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

Re: Add Array values
by duff (Parson) on Dec 30, 2004 at 02:45 UTC

    Depending on your needs, you might want to use a module that supports vectors and vector operations. For instance, your example would look like this with PDL:

    #!/usr/bin/perl use PDL; my %hash = ( one => pdl(1,2,4), two => pdl(5,7,9), ); $hash{one} += pdl(7,8,11); print $hash{$_},"\n" for keys %hash;
Re: Add Array values
by Anonymous Monk on Dec 29, 2004 at 22:37 UTC
    i tried
    use strict; use warnings; use Data::Dumper; my %hash = ( one => [ 1, 2, 4 ], two => [ 5, 7, 9 ], ); my @add = ( 7, 8, 15 ); $hash{one} = [ map { $hash{one}{$_} + $add[$_] } (0 .. $#add) ]; print Dumper \%hash;
    but that says "Canīt coerce array into hash at line 13".

    why? it assigns an array ref.
      Greetings all,
      small syntax problem.
      try:
      $hash{one} = [ map { $hash{one}->[$_] + $add[$_] } (0 .. $#add)];

      -InjunJoel
      "I do not feel obliged to believe that the same God who endowed us with sense, reason and intellect has intended us to forego their use." -Galileo
Re: Add Array values
by TedPride (Priest) on Dec 29, 2004 at 21:09 UTC
    EDIT: Disregard post. I didn't understand what was asked.

    ---------

    I don't see why you need complicated algorithms here. Push will take multiple values - why not use it? See below for various methods:

    use strict; use warnings; my %hash = ( one => [1,2,4], two => [5,7,9], ); my @new1 = (10,11,12); my $new2 = [13,14,15]; push(@{$hash{one}}, @new1); push(@{$hash{one}}, @$new2); push(@{$hash{one}}, 16, 17, 18); print join(',', @{$hash{one}});
      I think you misunderstood what I was asking. I didn't need to concat values to the end of the array. I acutally wanted to add the numbers to the array values.