2 `List::UtilsBy' - higher-order list utility functions
5 use List::UtilsBy qw( nsort_by min_by );
7 use File::stat qw( stat );
8 my @files_by_age = nsort_by { stat($_)->mtime } @files;
10 my $shortest_name = min_by { length } @names;
13 This module provides a number of list utility functions, all of which
14 take an initial code block to control their behaviour. They are
15 variations on similar core perl or `List::Util' functions of similar
16 names, but which use the block to control their behaviour. For example,
17 the core Perl function `sort' takes a list of values and returns them,
18 sorted into order by their string value. The `sort_by' function sorts
19 them according to the string value returned by the extra function, when
22 my @names_sorted = sort @names;
24 my @people_sorted = sort_by { $_->name } @people;
27 @vals = sort_by { KEYFUNC } @vals
28 Returns the list of values sorted according to the string values
29 returned by the `KEYFUNC' block or function. A typical use of this may
30 be to sort objects according to the string value of some accessor, such
33 sort_by { $_->name } @people
35 The key function is called in scalar context, being passed each value in
36 turn as both `$_' and the only argument in the parameters, `@_'. The
37 values are then sorted according to string comparisons on the values
42 sort { $a->name cmp $b->name } @people
44 except that it guarantees the `name' accessor will be executed only once
47 One interesting use-case is to sort strings which may have numbers
48 embedded in them "naturally", rather than lexically.
50 sort_by { s/(\d+)/sprintf "%09d", $1/eg; $_ } @strings
52 This sorts strings by generating sort keys which zero-pad the embedded
53 numbers to some level (9 digits in this case), helping to ensure the
54 lexical sort puts them in the correct order.
56 @vals = nsort_by { KEYFUNC } @vals
57 Similar to `sort_by' but compares its key values numerically.
59 @vals = rev_sort_by { KEYFUNC } @vals
60 @vals = rev_nsort_by { KEYFUNC } @vals
61 Similar to `sort_by' and `nsort_by' but returns the list in the reverse
64 @vals = reverse sort_by { KEYFUNC } @vals
66 except that these functions are slightly more efficient because they
67 avoid the final `reverse' operation.
69 $optimal = max_by { KEYFUNC } @vals
70 @optimal = max_by { KEYFUNC } @vals
71 Returns the (first) value from `@vals' that gives the numerically
72 largest result from the key function.
74 my $tallest = max_by { $_->height } @people
76 use File::stat qw( stat );
77 my $newest = max_by { stat($_)->mtime } @files;
79 In scalar context, the first maximal value is returned. In list context,
80 a list of all the maximal values is returned. This may be used to obtain
81 positions other than the first, if order is significant.
83 If called on an empty list, an empty list is returned.
85 For symmetry with the `nsort_by' function, this is also provided under
86 the name `nmax_by' since it behaves numerically.
88 $optimal = min_by { KEYFUNC } @vals
89 @optimal = min_by { KEYFUNC } @vals
90 Similar to `max_by' but returns values which give the numerically
91 smallest result from the key function. Also provided as `nmin_by'
93 @vals = uniq_by { KEYFUNC } @vals
94 Returns a list of the subset of values for which the key function block
95 returns unique values. The first value yielding a particular key is
96 chosen, subsequent values are rejected.
98 my @some_fruit = uniq_by { $_->colour } @fruit;
100 To select instead the last value per key, reverse the input list. If the
101 order of the results is significant, don't forget to reverse the result
104 my @some_fruit = reverse uniq_by { $_->colour } reverse @fruit;
106 %parts = partition_by { KEYFUNC } @vals
107 Returns a key/value list of ARRAY refs containing all the original
108 values distributed according to the result of the key function block.
109 Each value will be an ARRAY ref containing all the values which returned
110 the string from the key function, in their original order.
112 my %balls_by_colour = partition_by { $_->colour } @balls;
114 Because the values returned by the key function are used as hash keys,
115 they ought to either be strings, or at least well-behaved as strings
116 (such as numbers, or object references which overload stringification in
119 %counts = count_by { KEYFUNC } @vals
120 Returns a key/value list of integers, giving the number of times the key
121 function block returned the key, for each value in the list.
123 my %count_of_balls = count_by { $_->colour } @balls;
125 Because the values returned by the key function are used as hash keys,
126 they ought to either be strings, or at least well-behaved as strings
127 (such as numbers, or object references which overload stringification in
130 @vals = zip_by { ITEMFUNC } \@arr0, \@arr1, \@arr2,...
131 Returns a list of each of the values returned by the function block,
132 when invoked with values from across each each of the given ARRAY
133 references. Each value in the returned list will be the result of the
134 function having been invoked with arguments at that position, from
135 across each of the arrays given.
137 my @transposition = zip_by { [ @_ ] } @matrix;
139 my @names = zip_by { "$_[1], $_[0]" } \@firstnames, \@surnames;
141 print zip_by { "$_[0] => $_[1]\n" } [ keys %hash ], [ values %hash ];
143 If some of the arrays are shorter than others, the function will behave
144 as if they had `undef' in the trailing positions. The following two
145 lines are equivalent:
147 zip_by { f(@_) } [ 1, 2, 3 ], [ "a", "b" ]
148 f( 1, "a" ), f( 2, "b" ), f( 3, undef )
150 The item function is called by `map', so if it returns a list, the
151 entire list is included in the result. This can be useful for example,
152 for generating a hash from two separate lists of keys and values
154 my %nums = zip_by { @_ } [qw( one two three )], [ 1, 2, 3 ];
155 # %nums = ( one => 1, two => 2, three => 3 )
157 (A function having this behaviour is sometimes called `zipWith', e.g. in
158 Haskell, but that name would not fit the naming scheme used by this
161 $arr0, $arr1, $arr2, ... = unzip_by { ITEMFUNC } @vals
162 Returns a list of ARRAY references containing the values returned by the
163 function block, when invoked for each of the values given in the input
164 list. Each of the returned ARRAY references will contain the values
165 returned at that corresponding position by the function block. That is,
166 the first returned ARRAY reference will contain all the values returned
167 in the first position by the function block, the second will contain all
168 the values from the second position, and so on.
170 my ( $firstnames, $lastnames ) = unzip_by { m/^(.*?) (.*)$/ } @names;
172 If the function returns lists of differing lengths, the result will be
173 padded with `undef' in the missing elements.
175 This function is an inverse of `zip_by', if given a corresponding
178 @vals = extract_by { SELECTFUNC } @arr
179 Removes elements from the referenced array on which the selection
180 function returns true, and returns a list containing those elements.
181 This function is similar to `grep', except that it modifies the
182 referenced array to remove the selected values from it, leaving only the
185 my @red_balls = extract_by { $_->color eq "red" } @balls;
187 # Now there are no red balls in the @balls array
189 This function modifies a real array, unlike most of the other functions
190 in this module. Because of this, it requires a real array, not just a
193 This function is implemented by invoking `splice()' on the array, not by
194 constructing a new list and assigning it. One result of this is that
195 weak references will not be disturbed.
197 extract_by { !defined $_ } @refs;
199 will leave weak references weakened in the `@refs' array, whereas
201 @refs = grep { defined $_ } @refs;
203 will strengthen them all again.
205 @vals = weighted_shuffle_by { WEIGHTFUNC } @vals
206 Returns the list of values shuffled into a random order. The
207 randomisation is not uniform, but weighted by the value returned by the
208 `WEIGHTFUNC'. The probabilty of each item being returned first will be
209 distributed with the distribution of the weights, and so on recursively
210 for the remaining items.
212 @vals = bundle_by { BLOCKFUNC } $number, @vals
213 Similar to a regular `map' functional, returns a list of the values
214 returned by `BLOCKFUNC'. Values from the input list are given to the
215 block function in bundles of `$number'.
217 If given a list of values whose length does not evenly divide by
218 `$number', the final call will be passed fewer elements than the others.
222 These functions are currently all written in pure perl. Some at
223 least, may benefit from having XS implementations to speed up their
226 * Merge into List::Util or List::MoreUtils
227 This module shouldn't really exist. The functions should instead be
228 part of one of the existing modules that already contain many list
229 utility functions. Having Yet Another List Utilty Module just
232 I have attempted to contact the authors of both of the above
233 modules, to no avail; therefore I decided it best to write and
234 release this code here anyway so that it is at least on CPAN. Once
235 there, we can then see how best to merge it into an existing module.
238 Paul Evans <leonerd@leonerd.org.uk>