Array-GroupBy
view release on metacpan or search on metacpan
lib/Array/GroupBy.pm view on Meta::CPAN
that maximum salary.
use Array::GroupBy;
use List::Util qw( max );
# salary dataset
my @amounts = (
[ "Smith, J", 2009, 65 ],
[ "Smith, J", 2010, 63 ],
...
[ "Brown, F", 2006, 45 ],
[ "Brown, F", 2007, 47 ],
...
);
my $iter = igroup_by(
data => \@amounts,
compare => sub { $_[0]->[0] eq $_[1]->[0] },
);
while (my $subset = $iter->()) {
my $max_sal = max map { $_->[2] } @$subset; # max salary
print "Name: $subset->[0]->[0], ",
"Max Salary: $max_sal, Year(s) max salary reached: ",
join(', ',
map { $_->[1] }
grep { $_->[2] == $max_sal } @$subset
),
"\n";
}
See C<t/5.t> for code.
=head3 Example 4: Building objects
This is the real, "scratch-my-itch" reason for this module: to be able to take
multi-level data generated by SQL, and build objects from
the returned data, in this example Moose objects.
The hypothetical situation being modelled in the database
is that patients make multiple
visits to a doctor on several occasions and on each visit receive a diagnosis
of their condition.
So object I<Visit> has three attributes, the date the visit took place, the
name of the doctor, and the diagnosis. Object I<Patient> has a first and last
name and a list of Visits. To keep it simple, all scalar attributes are
strings. We assume all patients have unique (First, Last) name pairs.
package Visit;
use Moose;
has date => (is => 'ro', isa => 'Str');
has doctor => (is => 'ro', isa => 'Str');
has diagnosis => (is => 'ro', isa => 'Str');
package Patient;
use Moose;
has last => (is => 'ro', isa => 'Str');
has first => (is => 'ro', isa => 'Str');
has Visits => (is => 'ro', isa => 'ArrayRef[Visit]');
no Moose;
use DBI;
...
my @result; # this will contain a list of Patient objects
my $sql = q{
SELECT
P.Last, P.First
,V.Date, V.Doctor, V.Diagnosis
FROM
Patient P
,Visit V
WHERE
V.Patient_key = P.Patient_key -- join clause
...
ORDER BY
P.Last, P.First
};
my $dbh = DBI->connect(...);
my $data = $dbh->selectall_arrayref($sql);
# rows of @$data contain: Last, First, Date, Doctor, Diagnosis
# at positions: [0] [1] [2] [3] [4]
my $iter = igroup_by(
data => $data,
compare => \&str_row_equal,
args => [ 0, 1 ],
);
while (my $subset = $iter->()) {
my @visits = map { Visit->new(
date => $_[2],
doctor => $_[3],
diagnosis => $_[4],
)
} @$subset;
push @result, Patient->new(
last => $subset->[0]->[0],
first => $subset->[0]->[1],
Visit => \@visits,
);
}
See C<t/6.t> for code.
=head1 DIAGNOSTICS
Most error diagnostics are generated by the C<Params::Validate> module
which C<igroup_by()> uses for argument validation.
The C<data =E<gt> ...> and C<compare =E<gt> ...> parameters are mandatory.
( run in 0.526 second using v1.01-cache-2.11-cpan-39bf76dae61 )