1NAME 2 3 List::UtilsBy - higher-order list utility functions 4 5SYNOPSIS 6 7 use List::UtilsBy qw( nsort_by min_by ); 8 9 use File::stat qw( stat ); 10 my @files_by_age = nsort_by { stat($_)->mtime } @files; 11 12 my $shortest_name = min_by { length } @names; 13 14DESCRIPTION 15 16 This module provides a number of list utility functions, all of which 17 take an initial code block to control their behaviour. They are 18 variations on similar core perl or List::Util functions of similar 19 names, but which use the block to control their behaviour. For example, 20 the core Perl function sort takes a list of values and returns them, 21 sorted into order by their string value. The "sort_by" function sorts 22 them according to the string value returned by the extra function, when 23 given each value. 24 25 my @names_sorted = sort @names; 26 27 my @people_sorted = sort_by { $_->name } @people; 28 29FUNCTIONS 30 31 All functions added since version 0.04 unless otherwise stated, as the 32 original names for earlier versions were renamed. 33 34 sort_by 35 36 @vals = sort_by { KEYFUNC } @vals 37 38 Returns the list of values sorted according to the string values 39 returned by the KEYFUNC block or function. A typical use of this may be 40 to sort objects according to the string value of some accessor, such as 41 42 sort_by { $_->name } @people 43 44 The key function is called in scalar context, being passed each value 45 in turn as both $_ and the only argument in the parameters, @_. The 46 values are then sorted according to string comparisons on the values 47 returned. 48 49 This is equivalent to 50 51 sort { $a->name cmp $b->name } @people 52 53 except that it guarantees the name accessor will be executed only once 54 per value. 55 56 One interesting use-case is to sort strings which may have numbers 57 embedded in them "naturally", rather than lexically. 58 59 sort_by { s/(\d+)/sprintf "%09d", $1/eg; $_ } @strings 60 61 This sorts strings by generating sort keys which zero-pad the embedded 62 numbers to some level (9 digits in this case), helping to ensure the 63 lexical sort puts them in the correct order. 64 65 nsort_by 66 67 @vals = nsort_by { KEYFUNC } @vals 68 69 Similar to "sort_by" but compares its key values numerically. 70 71 rev_sort_by 72 73 rev_nsort_by 74 75 @vals = rev_sort_by { KEYFUNC } @vals 76 77 @vals = rev_nsort_by { KEYFUNC } @vals 78 79 Since version 0.06. 80 81 Similar to "sort_by" and "nsort_by" but returns the list in the reverse 82 order. Equivalent to 83 84 @vals = reverse sort_by { KEYFUNC } @vals 85 86 except that these functions are slightly more efficient because they 87 avoid the final reverse operation. 88 89 max_by 90 91 $optimal = max_by { KEYFUNC } @vals 92 93 @optimal = max_by { KEYFUNC } @vals 94 95 Returns the (first) value from @vals that gives the numerically largest 96 result from the key function. 97 98 my $tallest = max_by { $_->height } @people 99 100 use File::stat qw( stat ); 101 my $newest = max_by { stat($_)->mtime } @files; 102 103 In scalar context, the first maximal value is returned. In list 104 context, a list of all the maximal values is returned. This may be used 105 to obtain positions other than the first, if order is significant. 106 107 If called on an empty list, an empty list is returned. 108 109 For symmetry with the "nsort_by" function, this is also provided under 110 the name nmax_by since it behaves numerically. 111 112 min_by 113 114 $optimal = min_by { KEYFUNC } @vals 115 116 @optimal = min_by { KEYFUNC } @vals 117 118 Similar to "max_by" but returns values which give the numerically 119 smallest result from the key function. Also provided as nmin_by 120 121 minmax_by 122 123 ( $minimal, $maximal ) = minmax_by { KEYFUNC } @vals 124 125 Since version 0.11. 126 127 Similar to calling both "min_by" and "max_by" with the same key 128 function on the same list. This version is more efficient than calling 129 the two other functions individually, as it has less work to perform 130 overall. In the case of ties, only the first optimal element found in 131 each case is returned. Also provided as nminmax_by. 132 133 uniq_by 134 135 @vals = uniq_by { KEYFUNC } @vals 136 137 Returns a list of the subset of values for which the key function block 138 returns unique values. The first value yielding a particular key is 139 chosen, subsequent values are rejected. 140 141 my @some_fruit = uniq_by { $_->colour } @fruit; 142 143 To select instead the last value per key, reverse the input list. If 144 the order of the results is significant, don't forget to reverse the 145 result as well: 146 147 my @some_fruit = reverse uniq_by { $_->colour } reverse @fruit; 148 149 Because the values returned by the key function are used as hash keys, 150 they ought to either be strings, or at least well-behaved as strings 151 (such as numbers, or object references which overload stringification 152 in a suitable manner). 153 154 partition_by 155 156 %parts = partition_by { KEYFUNC } @vals 157 158 Returns a key/value list of ARRAY refs containing all the original 159 values distributed according to the result of the key function block. 160 Each value will be an ARRAY ref containing all the values which 161 returned the string from the key function, in their original order. 162 163 my %balls_by_colour = partition_by { $_->colour } @balls; 164 165 Because the values returned by the key function are used as hash keys, 166 they ought to either be strings, or at least well-behaved as strings 167 (such as numbers, or object references which overload stringification 168 in a suitable manner). 169 170 count_by 171 172 %counts = count_by { KEYFUNC } @vals 173 174 Since version 0.07. 175 176 Returns a key/value list of integers, giving the number of times the 177 key function block returned the key, for each value in the list. 178 179 my %count_of_balls = count_by { $_->colour } @balls; 180 181 Because the values returned by the key function are used as hash keys, 182 they ought to either be strings, or at least well-behaved as strings 183 (such as numbers, or object references which overload stringification 184 in a suitable manner). 185 186 zip_by 187 188 @vals = zip_by { ITEMFUNC } \@arr0, \@arr1, \@arr2,... 189 190 Returns a list of each of the values returned by the function block, 191 when invoked with values from across each each of the given ARRAY 192 references. Each value in the returned list will be the result of the 193 function having been invoked with arguments at that position, from 194 across each of the arrays given. 195 196 my @transposition = zip_by { [ @_ ] } @matrix; 197 198 my @names = zip_by { "$_[1], $_[0]" } \@firstnames, \@surnames; 199 200 print zip_by { "$_[0] => $_[1]\n" } [ keys %hash ], [ values %hash ]; 201 202 If some of the arrays are shorter than others, the function will behave 203 as if they had undef in the trailing positions. The following two lines 204 are equivalent: 205 206 zip_by { f(@_) } [ 1, 2, 3 ], [ "a", "b" ] 207 f( 1, "a" ), f( 2, "b" ), f( 3, undef ) 208 209 The item function is called by map, so if it returns a list, the entire 210 list is included in the result. This can be useful for example, for 211 generating a hash from two separate lists of keys and values 212 213 my %nums = zip_by { @_ } [qw( one two three )], [ 1, 2, 3 ]; 214 # %nums = ( one => 1, two => 2, three => 3 ) 215 216 (A function having this behaviour is sometimes called zipWith, e.g. in 217 Haskell, but that name would not fit the naming scheme used by this 218 module). 219 220 unzip_by 221 222 $arr0, $arr1, $arr2, ... = unzip_by { ITEMFUNC } @vals 223 224 Since version 0.09. 225 226 Returns a list of ARRAY references containing the values returned by 227 the function block, when invoked for each of the values given in the 228 input list. Each of the returned ARRAY references will contain the 229 values returned at that corresponding position by the function block. 230 That is, the first returned ARRAY reference will contain all the values 231 returned in the first position by the function block, the second will 232 contain all the values from the second position, and so on. 233 234 my ( $firstnames, $lastnames ) = unzip_by { m/^(.*?) (.*)$/ } @names; 235 236 If the function returns lists of differing lengths, the result will be 237 padded with undef in the missing elements. 238 239 This function is an inverse of "zip_by", if given a corresponding 240 inverse function. 241 242 extract_by 243 244 @vals = extract_by { SELECTFUNC } @arr 245 246 Since version 0.05. 247 248 Removes elements from the referenced array on which the selection 249 function returns true, and returns a list containing those elements. 250 This function is similar to grep, except that it modifies the 251 referenced array to remove the selected values from it, leaving only 252 the unselected ones. 253 254 my @red_balls = extract_by { $_->color eq "red" } @balls; 255 256 # Now there are no red balls in the @balls array 257 258 This function modifies a real array, unlike most of the other functions 259 in this module. Because of this, it requires a real array, not just a 260 list. 261 262 This function is implemented by invoking splice on the array, not by 263 constructing a new list and assigning it. One result of this is that 264 weak references will not be disturbed. 265 266 extract_by { !defined $_ } @refs; 267 268 will leave weak references weakened in the @refs array, whereas 269 270 @refs = grep { defined $_ } @refs; 271 272 will strengthen them all again. 273 274 extract_first_by 275 276 $val = extract_first_by { SELECTFUNC } @arr 277 278 Since version 0.10. 279 280 A hybrid between "extract_by" and List::Util::first. Removes the first 281 element from the referenced array on which the selection function 282 returns true, returning it. 283 284 As with "extract_by", this function requires a real array and not just 285 a list, and is also implemented using splice so that weak references 286 are not disturbed. 287 288 If this function fails to find a matching element, it will return an 289 empty list in list context. This allows a caller to distinguish the 290 case between no matching element, and the first matching element being 291 undef. 292 293 weighted_shuffle_by 294 295 @vals = weighted_shuffle_by { WEIGHTFUNC } @vals 296 297 Since version 0.07. 298 299 Returns the list of values shuffled into a random order. The 300 randomisation is not uniform, but weighted by the value returned by the 301 WEIGHTFUNC. The probabilty of each item being returned first will be 302 distributed with the distribution of the weights, and so on recursively 303 for the remaining items. 304 305 bundle_by 306 307 @vals = bundle_by { BLOCKFUNC } $number, @vals 308 309 Since version 0.07. 310 311 Similar to a regular map functional, returns a list of the values 312 returned by BLOCKFUNC. Values from the input list are given to the 313 block function in bundles of $number. 314 315 If given a list of values whose length does not evenly divide by 316 $number, the final call will be passed fewer elements than the others. 317 318TODO 319 320 * XS implementations 321 322 These functions are currently all written in pure perl. Some at 323 least, may benefit from having XS implementations to speed up their 324 logic. 325 326 * Merge into List::Util or List::MoreUtils 327 328 This module shouldn't really exist. The functions should instead be 329 part of one of the existing modules that already contain many list 330 utility functions. Having Yet Another List Utilty Module just worsens 331 the problem. 332 333 I have attempted to contact the authors of both of the above modules, 334 to no avail; therefore I decided it best to write and release this 335 code here anyway so that it is at least on CPAN. Once there, we can 336 then see how best to merge it into an existing module. 337 338 Updated 2015/07/16: As I am now the maintainer of List::Util, some 339 amount of merging/copying should be possible. However, given the 340 latter's key position in the core perl distribution and head of the 341 "CPAN River" I am keen not to do this wholesale, but a selected pick 342 of what seems best, by a popular consensus. 343 344 * head and tail-like functions 345 346 Consider perhaps 347 348 head_before { COND } LIST # excludes terminating element 349 head_upto { COND } LIST # includes terminating element 350 351 tail_since { COND } LIST # includes initiating element 352 tail_after { COND } LIST # excludes initiating element 353 354 (See also https://rt.cpan.org/Ticket/Display.html?id=105907). 355 356AUTHOR 357 358 Paul Evans <leonerd@leonerd.org.uk> 359 360