epic-ts
[kivitendo-erp.git] / doc / modules / README.List-UtilsBy
1 NAME
2     `List::UtilsBy' - higher-order list utility functions
3
4 SYNOPSIS
5      use List::UtilsBy qw( nsort_by min_by );
6
7      use File::stat qw( stat );
8      my @files_by_age = nsort_by { stat($_)->mtime } @files;
9
10      my $shortest_name = min_by { length } @names;
11
12 DESCRIPTION
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
20     given each value.
21
22      my @names_sorted = sort @names;
23
24      my @people_sorted = sort_by { $_->name } @people;
25
26 FUNCTIONS
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
31     as
32
33      sort_by { $_->name } @people
34
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
38     returned.
39
40     This is equivalent to
41
42      sort { $a->name cmp $b->name } @people
43
44     except that it guarantees the `name' accessor will be executed only once
45     per value.
46
47     One interesting use-case is to sort strings which may have numbers
48     embedded in them "naturally", rather than lexically.
49
50      sort_by { s/(\d+)/sprintf "%09d", $1/eg; $_ } @strings
51
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.
55
56   @vals = nsort_by { KEYFUNC } @vals
57     Similar to `sort_by' but compares its key values numerically.
58
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
62     order. Equivalent to
63
64      @vals = reverse sort_by { KEYFUNC } @vals
65
66     except that these functions are slightly more efficient because they
67     avoid the final `reverse' operation.
68
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.
73
74      my $tallest = max_by { $_->height } @people
75
76      use File::stat qw( stat );
77      my $newest = max_by { stat($_)->mtime } @files;
78
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.
82
83     If called on an empty list, an empty list is returned.
84
85     For symmetry with the `nsort_by' function, this is also provided under
86     the name `nmax_by' since it behaves numerically.
87
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'
92
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.
97
98      my @some_fruit = uniq_by { $_->colour } @fruit;
99
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
102     as well:
103
104      my @some_fruit = reverse uniq_by { $_->colour } reverse @fruit;
105
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.
111
112      my %balls_by_colour = partition_by { $_->colour } @balls;
113
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
117     a suitable manner).
118
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.
122
123      my %count_of_balls = count_by { $_->colour } @balls;
124
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
128     a suitable manner).
129
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.
136
137      my @transposition = zip_by { [ @_ ] } @matrix;
138
139      my @names = zip_by { "$_[1], $_[0]" } \@firstnames, \@surnames;
140
141      print zip_by { "$_[0] => $_[1]\n" } [ keys %hash ], [ values %hash ];
142
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:
146
147      zip_by { f(@_) } [ 1, 2, 3 ], [ "a", "b" ]
148      f( 1, "a" ), f( 2, "b" ), f( 3, undef )
149
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
153
154      my %nums = zip_by { @_ } [qw( one two three )], [ 1, 2, 3 ];
155      # %nums = ( one => 1, two => 2, three => 3 )
156
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
159     module).
160
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.
169
170      my ( $firstnames, $lastnames ) = unzip_by { m/^(.*?) (.*)$/ } @names;
171
172     If the function returns lists of differing lengths, the result will be
173     padded with `undef' in the missing elements.
174
175     This function is an inverse of `zip_by', if given a corresponding
176     inverse function.
177
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
183     unselected ones.
184
185      my @red_balls = extract_by { $_->color eq "red" } @balls;
186
187      # Now there are no red balls in the @balls array
188
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
191     list.
192
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.
196
197      extract_by { !defined $_ } @refs;
198
199     will leave weak references weakened in the `@refs' array, whereas
200
201      @refs = grep { defined $_ } @refs;
202
203     will strengthen them all again.
204
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.
211
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'.
216
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.
219
220 TODO
221     * XS implementations
222         These functions are currently all written in pure perl. Some at
223         least, may benefit from having XS implementations to speed up their
224         logic.
225
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
230         worsens the problem.
231
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.
236
237 AUTHOR
238     Paul Evans <leonerd@leonerd.org.uk>