Data-Bucketeer
view release on metacpan - search on metacpan
view release on metacpan or search on metacpan
lib/Data/Bucketeer.pm view on Meta::CPAN
#pod
#pod my $cost = $buck->result_for( 701 ); # cost is 3
#pod
#pod By default, the values I<exclusive minima>. For example, above, you end up
#pod with a result of C<3> by having an input C<strictly greater than> 500, and
#pod C<less than or equal to> 500. If you want to use a different operator, you can
#pod specify it like this:
#pod
#pod my $buck = Data::Bucketeer->new( '>=', {
#pod 1 => 10,
#pod 101 => 5,
#pod 201 => 4,
#pod 501 => 3,
#pod 1001 => 2,
#pod });
#pod
#pod my $cost = $buck->result_for( 701 ); # cost is 3
#pod
#pod This distinction can be useful when dealing with non-integers. The understood
#pod operators are:
#pod
#pod =for :list
#pod * >
#pod * >=
#pod * <=
#pod * <
#pod
#pod If the result value is a code reference, it will be invoked with C<$_> set to
#pod the input. This can be used for dynamically generating results, or to throw
#pod exceptions. Here is a contrived example of exception-throwing:
#pod
#pod my $greeting = Data::Bucketeer->new( '>=', {
#pod '-Inf' => sub { die "secs-into-day must be between 0 and 86399; got $_" },
#pod
#pod 0 => "Good evening.",
#pod 28_800 => "Good morning.",
#pod 43_200 => "Good afternoon.",
#pod 61_200 => "Good evening.",
#pod
#pod 86_400 => sub { die "secs-into-day must be between 0 and 86399; got $_" },
#pod });
#pod
#pod =cut
sub new {
my ($class, @rest) = @_;
unshift @rest, '>' if ref $rest[0];
my ($type, $buckets) = @rest;
my @non_num = grep { ! Scalar::Util::looks_like_number($_) or /NaN/i }
keys %$buckets;
croak "non-numeric bucket boundaries: @non_num" if @non_num;
my $guts = bless {
buckets => $buckets,
picker => $class->__picker_for($type),
};
return bless $guts => $class;
}
my %operator = (
'>' => sub {
my ($self, $this) = @_;
first { $this > $_ } sort { $b <=> $a } keys %{ $self->{buckets} };
},
'>=' => sub {
my ($self, $this) = @_;
first { $this >= $_ } sort { $b <=> $a } keys %{ $self->{buckets} };
},
'<=' => sub {
my ($self, $this) = @_;
first { $this <= $_ } sort { $a <=> $b } keys %{ $self->{buckets} };
},
'<' => sub {
my ($self, $this) = @_;
first { $this < $_ } sort { $a <=> $b } keys %{ $self->{buckets} };
},
);
sub __picker_for {
my ($self, $type) = @_;
return($operator{ $type } || croak("unknown bucket operator: $type"));
}
#pod =method result_for
#pod
#pod my $result = $buck->result_for( $input );
#pod
#pod This returns the result for the given input, as described L<above|/OVERVIEW>.
#pod
#pod =cut
sub result_for {
my ($self, $input) = @_;
my ($bound, $result) = $self->bound_and_result_for($input);
return $result;
}
#pod =method bound_and_result_for
#pod
#pod my ($bound, $result) = $buck->bound_and_result_for( $input );
#pod
#pod This returns two values: the boundary key whose result was used, and the
#pod result itself.
#pod
#pod Using the item quantity price above, for example:
#pod
#pod my $buck = Data::Bucketeer->new({
#pod 0 => 10,
#pod 100 => 5,
#pod 200 => 4,
#pod 500 => 3,
#pod 1000 => 2,
#pod });
#pod
view all matches for this distributionview release on metacpan - search on metacpan
( run in 1.096 second using v1.00-cache-2.02-grep-82fe00e-cpan-1925d2aa809 )