Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

+= a hash slice?

by Random_Walk (Prior)
on Jun 01, 2015 at 08:40 UTC ( [id://1128531]=perlquestion: print w/replies, xml ) Need Help??

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

Dear Folks

I want to do something like this:

use strict; use warnings; use Data::Dumper; my %totals; for(1..10){ @totals{qw(a b c)} += (1,2,3); } print Dumper \%totals;

And end up with

%totals = ( 'a' => 10, 'b' => 20, 'c' => 30, );

But of course I get %totals set to

( 'a' => undef, 'b' => undef, 'c' => 30, );

How would you folks keep such hash of running totals

Cheers,
R.

Pereant, qui ante nos nostra dixerunt!

Replies are listed 'Best First'.
Re: += a hash slice?
by choroba (Cardinal) on Jun 01, 2015 at 09:13 UTC
    You can assign a list to a hash slice, but that's about it. You need another loop:
    my %add = ( a => 1, b => 2, c => 3, ); for (1 .. 10) { $totals{$_} += $add{$_} for keys %add; } print Dumper(\%totals);

    Or, you use each:

    while (my ($k, $v) = each %add) { $totals{$k} += $v; }
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      Your first suggestion is pretty much the solution I used. It's clear for future maintainers.

      Cheers,
      R.

      Pereant, qui ante nos nostra dixerunt!
Re: += a hash slice?
by hdb (Monsignor) on Jun 01, 2015 at 11:35 UTC

    For a casual counter this might be overkill, but you could use a closure:

    use strict; use warnings; use Data::Dumper; sub make_counter { my ( $tally, @labels ) = @_; return sub { $tally->{$_} += shift for @labels } } my %totals; my $counter = make_counter \%totals, qw(a b c); for(1..10){ $counter->(1,2,3); } print Dumper \%totals;

      I love this solution, but it would scare the horses; I went with the simpler for loop version.

      Cheers,
      R.

      Pereant, qui ante nos nostra dixerunt!
Re: += a hash slice?
by kroach (Pilgrim) on Jun 01, 2015 at 12:48 UTC

    How about something like this?

    use strict; use warnings; use Data::Dumper; my %totals; for (1 .. 10) { my @plus = (1, 2, 3); @totals{qw(a b c)} = map { $_ + shift @plus } @totals{qw(a b c)}; } print Dumper \%totals;

    The map will add the first element of @plus to each element of the slice in order. However, since the first element gets shifted, $totals{a} gets incremented by 1, $totals{b} by 2 and $totals{c} by 3.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1128531]
Approved by hdb
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (2)
As of 2024-04-20 03:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found