Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Add multiple values of hash key

491 views
Skip to first unread message

F Massion

unread,
Mar 19, 2016, 2:18:41 PM3/19/16
to
Hi,

I have built a hash with multiple values per key. The values are numeric and I would like to add all the values per key get a list of key with the sum of values. When it comes to add the values I get stuck. Anyone has a hint? Her my code:

#!/usr/bin/perl -w
use utf8;
binmode(STDOUT, 'utf8');
open (DATA, '<:utf8', 'a.txt') or die ("file not found. $!");

my %hash = ();
my (@array) =<DATA>;
foreach my $var (@array)
{
chomp $var;
my ($key1, $key2, $value) = split(/\t/, $var);
my $key = "$key1\t$key2";
push( @{$hash{$key}}, $value );
}
foreach $key (sort keys %hash)
{
print "$key: @{$hash{$key}}\n"; # How can I add the values stored in the value array?
}
__END__

My data:
$key1 TAB $key2 TAB $value

RecordID001 adjustment washer 100
RecordID001 adjustment washer 1
RecordID001 adjustment washer 2
RecordID001 adjustment washer 2
RecordID002 scraper plate 0
RecordID003 scraper plate, lh side 0
RecordID004 scraper plate, rh side 0

Expected result

RecordID001 adjustment washer 105
RecordID002 scraper plate 0
RecordID003 scraper plate, lh side 0
RecordID004 scraper plate, rh side 0

HASM

unread,
Mar 19, 2016, 2:58:14 PM3/19/16
to
F Massion <fmas...@web.de> writes:

> I have built a hash with multiple values per key. The values
> are numeric and I would like to add all the values per key
> get a list of key with the sum of values. When it comes to
> add the values I get stuck. Anyone has a hint? Her my code:

Quickly worked ... seems to work. -- HASM


#!/usr/bin/perl -w
use strict;
use utf8;
binmode(STDOUT, 'utf8');
open (DATA, '<:utf8', 'a.txt') or die ("file not found. $!");

my %hash = ();
while (my $var = <DATA>)
{
chomp $var;
my ($key1, $key2, $value) = split(/\t/, $var);
$hash{"$key1\t$key2"} += $value;
}
foreach my $key (sort keys %hash)
{
print "$key: $hash{$key}\n";
}


George Mpouras

unread,
Mar 19, 2016, 4:38:02 PM3/19/16
to
On 19/3/2016 20:18, F Massion wrote:
> RecordID001 adjustment washer 100
> RecordID001 adjustment washer 1
> RecordID001 adjustment washer 2
> RecordID001 adjustment washer 2
> RecordID002 scraper plate 0
> RecordID003 scraper plate, lh side 0
> RecordID004 scraper plate, rh side 0


my %hash;
while(<DATA>) {
my @field = split /\s+/;
$hash{join ' ', @field[0..$#field-1]} += $field[-1]
}

use Data::Dumper; print Dumper \%hash;

__DATA__

Rainer Weikusat

unread,
Mar 20, 2016, 8:10:25 AM3/20/16
to
F Massion <fmas...@web.de> writes:
> I have built a hash with multiple values per key. The values are
> numeric and I would like to add all the values per key get a list of
> key with the sum of values. When it comes to add the values I get
> stuck. Anyone has a hint?

Use a for loop and an accumulator variable to sum up the values in each
array prior to printing. Modified example:

----------
#!/usr/bin/perl -w
use utf8;
binmode(STDOUT, 'utf8');

my %hash;

foreach my $var (<DATA>)
{
chomp $var;
my ($key1, $key2, $value) = split(/\t/, $var);
my $key = "$key1\t$key2";
push( @{$hash{$key}}, $value );
}
foreach $key (sort keys %hash)
{
my $sum = 0;
$sum += $_ for @{$hash{$key}};

print "$key: $sum\n";
}
__END__
RecordID001 adjustment washer 100
RecordID001 adjustment washer 1
RecordID001 adjustment washer 2
RecordID001 adjustment washer 2
RecordID002 scraper plate 0
RecordID003 scraper plate, lh side 0
RecordID004 scraper plate, rh side 0
------------

NB: Even when "I'm afraid of type conversions!" warnings are enabled,
trying to 'initialize' a newly created hash by assigning an empty list to
it is a total no-op.

F Massion

unread,
Mar 20, 2016, 10:45:03 AM3/20/16
to
Thanks to all of you for your help. Retrospectively everything is 'easy' ;-)

This solution works perfectly for me:
#!/usr/bin/perl -w
use strict;

use utf8;
binmode(STDOUT, 'utf8');
open (DATA, '<:utf8', 'a.txt') or die ("file not found. $!");

my %hash = ();

while (my $var = <DATA>)

{
chomp $var;
my ($key1, $key2, $value) = split(/\t/, $var);

$hash{"$key1\t$key2"} += $value;
}
foreach my $key (sort keys %hash)
{
print "$key: $hash{$key}\n";
}

Aaron Baugher

unread,
Mar 21, 2016, 11:39:07 AM3/21/16
to
F Massion <fmas...@web.de> writes:

> I have built a hash with multiple values per key. The values are numeric and
> I would like to add all the values per key get a list of key with the sum of
> values. When it comes to add the values I get stuck. Anyone has a hint? Her
> my code:

You could write a simple function that returns the sum of its arguments (or
use sum() from List::Util), and pass each key's array to it. For example:

#!/usr/bin/env perl
use 5.010; use warnings; use strict;

my %hash;
foreach my $line (<DATA>) {
chomp $line;
my ($key1, $key2, $value) = split /\t/, $line;
push @{$hash{"$key1\t$key2"}}, $value;
}
foreach my $key (sort keys %hash) {
say "$key: ", sum(@{$hash{$key}});
}

sub sum {
my $n = shift @_;
return $n unless @_;
return $n + sum(@_);
}

__DATA__
RecordID001 adjustment washer 100
RecordID001 adjustment washer 1
RecordID001 adjustment washer 2
RecordID001 adjustment washer 2
RecordID002 scraper plate 0
RecordID003 scraper plate, lh side 6
RecordID004 scraper plate, rh side 50
RecordID004 scraper plate, rh side 51

--
Aaron -- aaron.baugher.biz

Trudge

unread,
Mar 24, 2016, 12:04:09 AM3/24/16
to
X< ========== cut here ========== X<
#!/usr/bin/perl -w
use warnings;
use strict;
use utf8;

my %Sums = (); # unique list of $key values
my $key;
my ($key1, $key2, $value,$valueSum);
$valueSum=0;
while (<DATA>)
{
chomp $_;
($key1, $key2, $value) = split(/\t/, $_);
$key = "$key1\t$key2";
$Sums{$key}{sum} += $value;
$Sums{$key}{count}++;
}
foreach $key ( sort keys %Sums)
{
print "$key: $Sums{$key}{sum}\n";
}
__DATA__
RecordID001 adjustment washer 100
RecordID001 adjustment washer 1
RecordID001 adjustment washer 2
RecordID001 adjustment washer 2
RecordID002 scraper plate 0
RecordID003 scraper plate, lh side 0
RecordID004 scraper plate, rh side 0
=========================================

Results:
RecordID001 adjustment washer: 105
RecordID002 scraper plate: 0
RecordID003 scraper plate, lh side: 0
RecordID004 scraper plate, rh side: 0


--
MouthBreather
www.softouch.on.ca

0 new messages