in reply to How to loop over groups

Anyone developed a clean solution for this? Any advice would be appreciated.

If you use some SQL server, use its capabilities to do the work for you. I know MySQL can use:

SELECT foo, SUM(bar) FROM xyzzy GROUP BY foo
If you're not using SQL, or your SQL doesn't have this functionality, I'd sum first, and iterate later:
my @data = ( [ 'a', 1 ], [ 'a', 2 ], [ 'b', 3 ], [ 'b', 4 ] ); my %totals; my @order; for (@data) { push @order, $_->[0] unless exists $totals{$_->[0]}; $totals{$_->[0]} += $_->[1]; } for (@order) { # Do something with $totals{$_} }
If order is not important, leave out all @order stuff, and iterate over keys %totals;

U28geW91IGNhbiBhbGwgcm90MTMgY
W5kIHBhY2soKS4gQnV0IGRvIHlvdS
ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
geW91IHNlZSBpdD8gIC0tIEp1ZXJk

Replies are listed 'Best First'.
Re: Re: How to loop over groups
by eisenstein (Acolyte) on Apr 02, 2002 at 08:19 UTC
    True. But it gets much worse when I'm printing out a header for the section, then the individual rows in that group, then the total. Thinking about it now, the trickiest part is knowing when to print out the next group's header. Is there any way to avoid using the "$old" temp variable to handle that?
    @a = (['a',1],['a',2],['b',3],['b',4]); # "db read" my $old; my $total = 0; # init foreach my $row (@a) { if ($old && $old ne $row->[0]) { print "$old: $total\n"; # finish row block $total = 0; # init print "Section $row->[0]\n"; } $total += $row->[1]; # processrow block print "$row->[1]\n"; $old = $row->[0]; # set temp variable } print "$old: $total\n"; # finish row block
      Sure, just rearrange your data.

      By building a hash which groups the rows together, your problem goes away.

      @a = (['a',1],['a',2],['b',3],['b',4]); # "db read" my %aByGroup; foreach(@a) { # you could just push $_->[1], but I'm guessing your # data is more complex, so I'm keeping the whole row push @{$aByGroup{$_->[0]}},$_; } my $old; foreach my $group (sort keys %aByGroup) { my $total = 0; # init print "Section $group\n"; foreach my $row(@{$aByGroup{$group}}) { $total += $row->[1]; # processrow block print "$row->[1]\n"; } print "$group: $total\n"; # finish row block }

      --
      Mike