view release on metacpan or search on metacpan
lib/List/UtilsBy.pm view on Meta::CPAN
99100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135them
"naturally"
, rather than lexically.
sort_by { s/(\d+)/
sprintf
"%09d"
, $1/eg;
$_
}
@strings
This sorts strings by generating
sort
keys
which zero-pad the embedded numbers
to some level (9 digits in this case), helping to ensure the lexical
sort
puts
them in the correct order.
=cut
sub sort_by(&@)
{
my $keygen = shift;
my @keys = map { local $_ = $_; scalar $keygen->( $_ ) } @_;
return @_[ sort { $keys[$a] cmp $keys[$b] } 0 .. $#_ ];
}
=head2 nsort_by
@vals = nsort_by { KEYFUNC } @vals
Similar to L</sort_by> but compares its key values numerically.
=cut
sub
nsort_by(&@)
{
my
$keygen
=
shift
;
my
@keys
=
map
{
local
$_
=
$_
;
scalar
$keygen
->(
$_
) }
@_
;
return
@_
[
sort
{
$keys
[
$a
] <=>
$keys
[
$b
] } 0 ..
$#_
];
}
=head2 rev_sort_by
=head2 rev_nsort_by
lib/List/UtilsBy.pm view on Meta::CPAN
143144145146147148149150151152153154155156157158159160161162163164165166167168169170171Similar to L</sort_by> and L</nsort_by> but returns the list in the
reverse
order. Equivalent to
@vals
=
reverse
sort_by { KEYFUNC }
@vals
except that these functions are slightly more efficient because they avoid
the final C<
reverse
> operation.
=cut
sub rev_sort_by(&@)
{
my $keygen = shift;
my @keys = map { local $_ = $_; scalar $keygen->( $_ ) } @_;
return @_[ sort { $keys[$b] cmp $keys[$a] } 0 .. $#_ ];
}
sub rev_nsort_by(&@)
{
my $keygen = shift;
my @keys = map { local $_ = $_; scalar $keygen->( $_ ) } @_;
return @_[ sort { $keys[$b] <=> $keys[$a] } 0 .. $#_ ];
}
=head2 max_by
$optimal = max_by { KEYFUNC } @vals
lib/List/UtilsBy.pm view on Meta::CPAN
184185186187188189190191192193194195196197198199200201202203list of all the maximal
values
is returned. This may be used to obtain
positions other than the first,
if
order is significant.
If called on an empty list, an empty list is returned.
For symmetry
with
the L</nsort_by> function, this is also provided under the
name C<nmax_by> since it behaves numerically.
=cut
sub max_by(&@)
{
my $code = shift;
return unless @_;
local $_;
my @maximal = $_ = shift @_;
my $max = $code->( $_ );
lib/List/UtilsBy.pm view on Meta::CPAN
222223224225226227228229230231232233234235236237238239240241
$optimal
= min_by { KEYFUNC }
@vals
@optimal
= min_by { KEYFUNC }
@vals
Similar to L</max_by> but returns
values
which give the numerically smallest
result from the key function. Also provided as C<nmin_by>
=cut
sub min_by(&@)
{
my $code = shift;
return unless @_;
local $_;
my @minimal = $_ = shift @_;
my $min = $code->( $_ );
lib/List/UtilsBy.pm view on Meta::CPAN
263264265266267268269270271272273274275276277278279280281282I<Since version 0.11.>
Similar to calling both L</min_by> and L</max_by>
with
the same key function
on the same list. This version is more efficient than calling the two other
functions individually, as it
has
less work to perform overall. In the case of
ties, only the first optimal element found in
each
case is returned. Also
provided as C<nminmax_by>.
=cut
sub minmax_by(&@)
{
my $code = shift;
return unless @_;
my $minimal = $_ = shift @_;
my $min = $code->( $_ );
return ( $minimal, $minimal ) unless @_;
lib/List/UtilsBy.pm view on Meta::CPAN
337338339340341342343344345346347348349350351352353354355356
my
@some_fruit
=
reverse
uniq_by {
$_
->colour }
reverse
@fruit
;
Because the
values
returned by the key function are used as hash
keys
, they
ought to either be strings, or at least well-behaved as strings (such as
numbers, or object references which overload stringification in a suitable
manner).
=cut
sub uniq_by(&@)
{
my $code = shift;
my %present;
return grep {
my $key = $code->( local $_ = $_ );
!$present{$key}++
} @_;
}
lib/List/UtilsBy.pm view on Meta::CPAN
366367368369370371372373374375376377378379380381382383384385386
my
%balls_by_colour
= partition_by {
$_
->colour }
@balls
;
Because the
values
returned by the key function are used as hash
keys
, they
ought to either be strings, or at least well-behaved as strings (such as
numbers, or object references which overload stringification in a suitable
manner).
=cut
sub partition_by(&@)
{
my $code = shift;
my %parts;
push @{ $parts{ $code->( local $_ = $_ ) } }, $_ for @_;
return %parts;
}
=head2 count_by
lib/List/UtilsBy.pm view on Meta::CPAN
394395396397398399400401402403404405406407408409410411412413414
my
%count_of_balls
= count_by {
$_
->colour }
@balls
;
Because the
values
returned by the key function are used as hash
keys
, they
ought to either be strings, or at least well-behaved as strings (such as
numbers, or object references which overload stringification in a suitable
manner).
=cut
sub count_by(&@)
{
my $code = shift;
my %counts;
$counts{ $code->( local $_ = $_ ) }++ for @_;
return %counts;
}
=head2 zip_by
lib/List/UtilsBy.pm view on Meta::CPAN
438439440441442443444445446447448449450451452453454455456457458a hash from two separate lists of
keys
and
values
my
%nums
= zip_by {
@_
} [
qw( one two three )
], [ 1, 2, 3 ];
# %nums = ( one => 1, two => 2, three => 3 )
(A function having this behaviour is sometimes called C<zipWith>, e.g. in
Haskell, but that name would not fit the naming scheme used by this module).
=cut
sub zip_by(&@)
{
my $code = shift;
@_ or return;
my $len = 0;
scalar @$_ > $len and $len = scalar @$_ for @_;
return map {
my $idx = $_;
lib/List/UtilsBy.pm view on Meta::CPAN
477478479480481482483484485486487488489490491492493494495496
my
(
$firstnames
,
$lastnames
) = unzip_by { m/^(.*?) (.*)$/ }
@names
;
If the function returns lists of differing lengths, the result will be padded
with
C<
undef
> in the missing elements.
This function is an inverse of L</zip_by>,
if
given
a corresponding inverse
function.
=cut
sub unzip_by(&@)
{
my $code = shift;
my @ret;
foreach my $idx ( 0 .. $#_ ) {
my @slice = $code->( local $_ = $_[$idx] );
$#slice = $#ret if @slice < @ret;
$ret[$_][$idx] = $slice[$_] for 0 .. $#slice;
}
lib/List/UtilsBy.pm view on Meta::CPAN
523524525526527528529530531532533534535536537538539540541542543
extract_by { !
defined
$_
}
@refs
;
will leave weak references weakened in the C<
@refs
> array, whereas
@refs
=
grep
{
defined
$_
}
@refs
;
will strengthen them all again.
=cut
sub extract_by(&\@)
{
my $code = shift;
my ( $arrref ) = @_;
my @ret;
for( my $idx = 0; ; $idx++ ) {
last if $idx > $#$arrref;
next unless $code->( local $_ = $arrref->[$idx] );
push @ret, splice @$arrref, $idx, 1, ();
lib/List/UtilsBy.pm view on Meta::CPAN
560561562563564565566567568569570571572573574575576577578579As
with
L</extract_by>, this function requires a real array and not just a
list, and is also implemented using C<
splice
> so that weak references are
not disturbed.
If this function fails to find a matching element, it will
return
an empty
list in list context. This allows a
caller
to distinguish the case between
no
matching element, and the first matching element being C<
undef
>.
=cut
sub extract_first_by(&\@)
{
my $code = shift;
my ( $arrref ) = @_;
foreach my $idx ( 0 .. $#$arrref ) {
next unless $code->( local $_ = $arrref->[$idx] );
return splice @$arrref, $idx, 1, ();
}
lib/List/UtilsBy.pm view on Meta::CPAN
587588589590591592593594595596597598599600601602603604605606607I<Since version 0.07.>
Returns the list of
values
shuffled into a random order. The randomisation is
not uniform, but weighted by the value returned by the C<WEIGHTFUNC>. The
probability of
each
item being returned first will be distributed
with
the
distribution of the weights, and so on recursively
for
the remaining items.
=cut
sub weighted_shuffle_by(&@)
{
my $code = shift;
my @vals = @_;
my @weights = map { $code->( local $_ = $_ ) } @vals;
my @ret;
while( @vals > 1 ) {
my $total = 0; $total += $_ for @weights;
my $select = int rand $total;
lib/List/UtilsBy.pm view on Meta::CPAN
627628629630631632633634635636637638639640641642643644645646647Similar to a regular C<
map
> functional, returns a list of the
values
returned
by C<BLOCKFUNC>. Values from the input list are
given
to the block function in
bundles of C<
$number
>.
If
given
a list of
values
whose
length
does not evenly divide by C<
$number
>,
the final call will be passed fewer elements than the others.
=cut
sub bundle_by(&@)
{
my $code = shift;
my $n = shift;
my @ret;
for( my ( $pos, $next ) = ( 0, $n ); $pos < @_; $pos = $next, $next += $n ) {
$next = @_ if $next > @_;
push @ret, $code->( @_[$pos .. $next-1] );
}
return @ret;
t/Unrandom.pm view on Meta::CPAN
5678910111213141516171819202122232425our
@EXPORT
=
qw( unrandomly )
;
our
$randhook
;
*CORE::GLOBAL::rand
=
sub
{
$randhook
?
$randhook
->(
$_
[0] ) :
rand
$_
[0] };
sub
unrandomly(&)
{
my
$code
=
shift
;
my
@rands
;
my
$randidx
;
local
$randhook
=
sub
{
my
(
$below
) =
@_
;
if
(
$randidx
>
$#rands
) {
push
@rands
, [ 0,
$below
];
$randidx
++;