NAME
List::OrderBy - Multi-key sorting using order_by and then_by
SYNOPSIS
use List::OrderBy;
my @sorted = order_by { ... }
then_by { ... }
then_by { ... } @unsorted;
DESCRIPTION
Routines to generate ordered lists using key extraction code blocks with support for multi-key sorting.
ROUTINES
- order_by { ... } @list
- order_by \&code, @list
-
The main routine takes a code block or subroutine reference and a list, applies the specified code to every element in the list to extract a sorting key, and then returns a list ordered according to the extracted keys, using
sort
and `<=>` internally. In the code block the list item value is available as$_
, and subroutines are additionally called with the value as first parameter.my @sorted = order_by { length } qw/xxx xx x/; # returns qw/x xx xxx/
- then_by { ... } @list
-
In a chain starting with
order_by
,then_by
specifies an additional ordering key extractor. The extracted key will be used to order elements if keys extracted by precedingorder_by
orthen_by
calls are equivalent.my @sorted = order_by { $_->width } then_by { $_->height } @shapes;
This would first sort elements by their width and then by their height.
- order_by_desc { ... } @list
-
Same as
order_by
but uses descending order. - order_cmp_by { ... } @list
-
Same as
order_by
but usescmp
to compare extracted keys. - order_cmp_by_desc { ... } @list
- then_cmp_by { ... } @list
- then_by_desc { ... } @list
- then_cmp_by_desc { ... } @list
-
Analogous to the similarily named routines.
EXPORTS
The functions order_by
, then_by
, order_cmp_by
, then_cmp_by
, order_by_desc
, then_by_desc
, order_cmp_by_desc
, and then_cmp_by_desc
, by default.
KNOWN ISSUES
This module is mainly an experiment to see how Schwartzian transforms can be avoided in code, considering the pattern can be difficult to read, and it becomes unmaintainable with multiple keys. There are a number of issues though, like how to manage side-effects: should the module call a secondary key extractor even when the key is not actually needed? Should the module ensure that the key extractor is called only once? Does the ordering between calls to the key extractors matter?
Another problem is of course naming, order_by { ... } then_by { ... }
is nice enough, but there does not seem to be a good way to add options like the comparison operator or ascending/descending behavior. Same for the side-effects question above if that was to be made configurable. A syntax with named parameters like in order_by :cmp :desc { ... }
would be better but is not yet available with Perl5.
One gotcha I've noticed is with sorting strings by length. Since they are strings, you might be inclined to use a cmp
variant, but order_cmp_by { length }
usually is not what authors want. In a draft version of this module I actually called the routine order_strings_by
, and switched to order_cmp_by
to make it less misleading.
AUTHOR / COPYRIGHT / LICENSE
Copyright (c) 2013 Bjoern Hoehrmann <bjoern@hoehrmann.de>.
This module is licensed under the same terms as Perl itself.