Collection-Categorized
view release on metacpan - search on metacpan
view release on metacpan or search on metacpan
lib/Collection/Categorized.pm view on Meta::CPAN
=head1 DESCRIPTION
The idea is that, given a list of junk, you want to find order in the
chaos. Write some categorizers (see below), dump your data in, and
get it out in some sort of meaningful order.
=head1 METHODS
=head2 new($coderef)
Create a categorized collection that categorizes its members
by the return value of C<$coderef>. Coderef is run with C<$_>
aliased to the element to categorize.
=head2 new([ category => $condition, ... ])
Create a categorized collection that categorizes its members
based on the passed category definition list. Example:
new([ positive => sub { $_ < 0 },
zero => sub { $_ == 0 },
negative => sub { $_ > 0 },
]);
This example creates three categories. The conditions are run in
order, and the first condition to match decides the category that
element is in. If an element doesn't match any of the three blocks
(unlikely in this case), then it is silently discarded. If you want
some sort of fallback, just add a condition that always matches (like
C<sub { 1 }>).
Note that you're passing an arrayref, not a hashref, because we want
to preserve order.
=cut
sub new {
my ($class, $ref) = @_;
my $self = {};
my $dispatch =
{ CODE => sub { $self->{_sorter} = transform $ref },
ARRAY => sub {
my %lookup = @$ref;
$lookup{$_} = transform $lookup{$_} for keys %lookup;
# with that out of the way, setup the sorter
$self->{_sorter} = sub {
my $arg = shift;
foreach my $category (grep { !ref $_ } @$ref) {
return $category if $lookup{$category}->($arg);
}
}
},
};
my $action = $dispatch->{ref $ref};
croak 'pass an ARRAY or CODE reference only' unless $action;
$action->();
$self->{_data} = {};
return bless $self => $class;
}
=head2 categories
Returns a list of categories in use
=cut
sub categories {
my $self = shift;
return keys %{$self->{_data}};
}
=head2 add($object)
Add an object to the collection.
=cut
sub add {
my ($self, @objects) = @_;
foreach (@objects) {
my $class = $self->_sorter->($_);
$self->_data->{$class} ||= [];
push @{$self->_data->{$class}}, $_;
}
return;
}
=head2 get($type)
Gets all elements of a certain type
=cut
sub get {
my ($self, $type) = @_;
return @{$self->_data->{$type}||[]};
}
=head2 all
Get every element in the collection
=cut
sub all {
my $self = shift;
return map { $self->get($_) } $self->categories;
}
=head2 edit(sub { change @_ })
Given a a subref, apply it to every type and change the members of the
type to be the return value of the sub.
Example:
# Input: ( category => data )
view all matches for this distributionview release on metacpan - search on metacpan
( run in 2.518 seconds using v1.00-cache-2.02-grep-82fe00e-cpan-1925d2aa809 )