in reply to RFC: Array::GroupBy
Not to belittle your efforts in any way, but IMHO your solution is far too complicated and hard to comprehend, and I believe this is because it tries to do too much. IMHO, the grouping function should be separate from any processing/analysis of the groups. If you simply return the groups to the caller, she can do whatever processing on them in her own way.
Here is how I would probably approach the problem:
Example: Show a count(*) of distinct values of the 'name' column:sub find_groups(&\@) { my( $keymap, $rows_ar ) = @_; my %groups; for ( @$rows_ar ) { push @{ $groups{ &$keymap } }, $_; } \%groups }
Example: Group by a key consisting of multiple columns concatenated:my $groups_hr = find_groups { $_->{'name'} } @rows; for my $k ( sort keys %$groups_hr ) { print "$k\t" . @{$groups_hr->{$k}} . "\n"; }
Example: Group by a key derived from the row by an arbitrarily complex function:find_groups { join $;, @{$_}{qw( name game score )} } @rows;
Example: Find numeric mean within each group of the values in the 'score' field:find_groups { $_->{'name'} eq 'foo' ? 1 : $_->{'game'} =~ /bar/ ? 2 : $_->{'score'} >= 500 ? 3 : 0 } @rows;
Sure, you could argue thatuse List::Util qw( sum ); my $groups_hr = find_groups { $_->{'name'} } @rows; for my $k ( sort keys %$groups_hr ) { my $avg = sum( map { $_->{'score'} } @{$groups_hr->{$k}} ) / @{$gr +oups_hr->{$k}}; print "$k\t$avg\n"; }
is an ugly way of extracting a column from a AoH table... but at least it's perlish. You could easily wrap that in a function if you wanted to.map { $_->{'score'} } @rows
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: RFC: Array::GroupBy
by Porculus (Hermit) on Jan 09, 2009 at 23:56 UTC |