List::AllUtils(3)

πŸ¦‹ List::AllUtils β€” the one-stop shop, bestie

So this is List::AllUtils(3), from the User Contributed Perl Documentation crew β€” and honestly? It's giving "finally, someone organized the group chat."

✨ VERSION ✨

version 0.19 πŸ’…

🌸 SYNOPSIS 🌸

    use List::AllUtils qw( first any );

    # _Everything_ from List::Util, List::SomeUtils, and List::UtilsBy
    use List::AllUtils qw( :all );

    my @numbers = ( 1, 2, 3, 5, 7 );
    # or don't import anything
    return List::AllUtils::first { $_ > 5 } @numbers;

πŸ’– DESCRIPTION πŸ’–

okay so picture this: you're out here like "was that helper in List::Util, List::SomeUtils, or List::UtilsBy??" and honestly I'm so over it. I sure am sick of it. And now you literally don't have to remember, because this module exports all the functions that either of those three modules defines. no cap.

Just so we're clear: all function documentation has been shamelessly copied from List::Util, List::SomeUtils and List::UtilsBy. 🫢

πŸ‘‘ Which One Wins? πŸ‘‘

okay this is the drama. Recently, List::Util started including some of the subs that used to only live in List::SomeUtils. Similarly, List::SomeUtils has a little overlap with List::UtilsBy. messy.

List::AllUtils used to always favor the subroutine provided by List::Util, List::SomeUtils or List::UtilsBy, in that order. But plot twist: as of List::Util 1.56, it included some functions, mesh and zip, with the same name as List::SomeUtils functions, but with different behavior. 😭

So going forward, we will always prefer backwards compatibility. Which means mesh and zip will always come from List::SomeUtils. If other incompatible functions get added to List::Util, those will also be skipped in favor of the List::SomeUtils version. protecting the vibe fr fr.

The docs below come from List::Util 1.56, List::SomeUtils 0.58, and List::UtilsBy 0.11.

⭐ WHAT IS EXPORTED? ⭐

Literally all this module does is load List::Util, List::SomeUtils, and List::UtilsBy, and then re-export everything that they provide. So regardless of the documentation below, you will get any subroutine that your installed version provides. that's it. that's the whole thing. ✨

πŸ”₯ LIST-REDUCTION FUNCTIONS πŸ”₯

The following set of functions all apply a given block of code to a list of values. icon behavior.

🧚 reduce

    $result = reduce { BLOCK } @list

Reduces @list by calling BLOCK in a scalar context multiple times, setting $a and $b each time. The first call will be with $a and $b set to the first two elements of the list, and subsequent calls happen by setting $a to the result of the previous call and $b to the next element in the list.

Returns the result of the last call to the BLOCK. If @list is empty then undef is returned. If @list only contains one element then that element is returned and BLOCK is not executed.

The following examples all demonstrate how reduce could be used to implement the other list-reduction functions in this module. (They are not in fact implemented like this, but instead in a more efficient manner in individual C functions. efficient king behavior.)

    $foo = reduce { defined($a)            ? $a :
                    $code->(local $_ = $b) ? $b :
                                             undef } undef, @list # first

    $foo = reduce { $a > $b ? $a : $b } 1..10       # max
    $foo = reduce { $a gt $b ? $a : $b } 'A'..'Z'   # maxstr
    $foo = reduce { $a < $b ? $a : $b } 1..10       # min
    $foo = reduce { $a lt $b ? $a : $b } 'aa'..'zz' # minstr
    $foo = reduce { $a + $b } 1 .. 10               # sum
    $foo = reduce { $a . $b } @bar                  # concat

    $foo = reduce { $a || $code->(local $_ = $b) } 0, @bar   # any
    $foo = reduce { $a && $code->(local $_ = $b) } 1, @bar   # all
    $foo = reduce { $a && !$code->(local $_ = $b) } 1, @bar  # none
    $foo = reduce { $a || !$code->(local $_ = $b) } 0, @bar  # notall
       # Note that these implementations do not fully short-circuit

If your algorithm requires that reduce produce an identity value, then make sure that you always pass that identity value as the first argument to prevent undef being returned:

  $foo = reduce { $a + $b } 0, @values;             # sum with 0 identity value

The above example code blocks also suggest how to use reduce to build a more efficient combined version of one of these basic functions and a map block. For example, to find the total length of all the strings in a list, we could use:

    $total = sum map { length } @strings;

However, this produces a list of temporary integer values as long as the original list of strings, only to reduce it down to a single value again. 😭 We can compute the same result more efficiently by using reduce with a code block that accumulates lengths by writing this instead:

    $total = reduce { $a + length $b } 0, @strings

The other scalar-returning list reduction functions are all specialisations of this generic idea. πŸ’…

🌈 reductions

    @results = reductions { BLOCK } @list

Since version 1.54.

Similar to reduce, except that it also returns the intermediate values along with the final result. As before, $a is set to the first element of the given list, and the BLOCK is then called once for remaining item in the list set into $b, with the result being captured for return as well as becoming the new value for $a.

The returned list will begin with the initial value for $a, followed by each return value from the block in order. The final value of the result will be identical to what the reduce function would have returned given the same block and list. bestie it's the receipts version.

    reduce     { "$a-$b" }  "a".."d"    # "a-b-c-d"
    reductions { "$a-$b" }  "a".."d"    # "a", "a-b", "a-b-c", "a-b-c-d"

πŸŽ€ any

    my $bool = any { BLOCK } @list;

Since version 1.33.

Similar to grep in that it evaluates BLOCK setting $_ to each element of @list in turn. any returns true if any element makes the BLOCK return a true value. If BLOCK never returns true or @list was empty then it returns false.

Many cases of using grep in a conditional can be written using any instead, as it can short-circuit after the first true result. queen of not doing extra work.

    if( any { length > 10 } @strings ) {
        # at least one string has more than 10 characters
    }
Note: Due to XS issues the block passed may be able to access the outer @_ directly. This is not intentional and will break under debugger. πŸ’€

πŸ“ all

    my $bool = all { BLOCK } @list;

Since version 1.33.

Similar to any, except that it requires all elements of the @list to make the BLOCK return true. If any element returns false, then it returns false. If the BLOCK never returns false or the @list was empty then it returns true.

Note: Due to XS issues the block passed may be able to access the outer @_ directly. This is not intentional and will break under debugger. πŸ’€

πŸ’€ none

πŸ’€ notall

    my $bool = none { BLOCK } @list;

    my $bool = notall { BLOCK } @list;

Since version 1.33.

Similar to any and all, but with the return sense inverted. none returns true only if no value in the @list causes the BLOCK to return true, and notall returns true only if not all of the values do. flipped, but make it fashion.

Note: Due to XS issues the block passed may be able to access the outer @_ directly. This is not intentional and will break under debugger. πŸ’€

⭐ first

    my $val = first { BLOCK } @list;

Similar to grep in that it evaluates BLOCK setting $_ to each element of @list in turn. first returns the first element where the result from BLOCK is a true value. If BLOCK never returns true or @list was empty then undef is returned. first place energy only.

    $foo = first { defined($_) } @list    # first defined value in @list
    $foo = first { $_ > $value } @list    # first value in @list which
                                          # is greater than $value

πŸ”₯ max

    my $num = max @list;

Returns the entry in the list with the highest numerical value. If the list is empty then undef is returned.

    $foo = max 1..10                # 10
    $foo = max 3,9,12               # 12
    $foo = max @bar, @baz           # whatever

🌸 maxstr

    my $str = maxstr @list;

Similar to max, but treats all the entries in the list as strings and returns the highest string as defined by the gt operator. If the list is empty then undef is returned.

    $foo = maxstr 'A'..'Z'          # 'Z'
    $foo = maxstr "hello","world"   # "world"
    $foo = maxstr @bar, @baz        # whatever

πŸ¦‹ min

    my $num = min @list;

Similar to max but returns the entry in the list with the lowest numerical value. If the list is empty then undef is returned.

    $foo = min 1..10                # 1
    $foo = min 3,9,12               # 3
    $foo = min @bar, @baz           # whatever

🧚 minstr

    my $str = minstr @list;

Similar to min, but treats all the entries in the list as strings and returns the lowest string as defined by the lt operator. If the list is empty then undef is returned.

    $foo = minstr 'A'..'Z'          # 'A'
    $foo = minstr "hello","world"   # "hello"
    $foo = minstr @bar, @baz        # whatever

πŸ’œ product

    my $num = product @list;

Since version 1.35.

Returns the numerical product of all the elements in @list. If @list is empty then 1 is returned.

    $foo = product 1..10            # 3628800
    $foo = product 3,9,12           # 324

✨ sum

    my $num_or_undef = sum @list;

Returns the numerical sum of all the elements in @list. For backwards compatibility, if @list is empty then undef is returned. yes, undef. it's a legacy thing, we don't question it.

    $foo = sum 1..10                # 55
    $foo = sum 3,9,12               # 24
    $foo = sum @bar, @baz           # whatever

🌈 sum0

    my $num = sum0 @list;

Since version 1.26.

Similar to sum, except this returns 0 when given an empty list, rather than undef. the fixed version, we love her.


πŸ”‘ KEY/VALUE PAIR LIST FUNCTIONS πŸ”‘

Okay bestie, these next ones are all inspired by List::Pairwise, and they eat an even-sized list of pairs. Those pairs can be key/value associations from a hash, or just a plain list of values. Every function here keeps the original ordering of the pairs, and they will not get confused by multiple pairs having the same β€œkey” value β€” they don’t even require that the first item of each pair be a plain string. πŸ’…

NOTE: At the time of writing, the following pair* functions that take a block do not modify the value of $_ inside the block, and instead operate using the $a and $b globals. This turned out to be a poor design, because it precludes the ability to provide a pairsort function. Better would be to pass pair-like objects as 2-element array references in $_, in a style similar to the return value of the pairs function. At some future version this behaviour may be added.

Until then, users are alerted NOT to rely on the value of $_ remaining unmodified between the outside and the inside of the control block. In particular, the following example is UNSAFE:

my @kvlist = ...

foreach (qw( some keys here )) {
   my @items = pairgrep { $a eq $_ } @kvlist;
   ...
}

Instead, write this using a lexical variable:

foreach my $key (qw( some keys here )) {
   my @items = pairgrep { $a eq $key } @kvlist;
   ...
}

pairs 🫢

my @pairs = pairs @kvlist;

Since version 1.29.

This is the convenient shortcut for working with even-sized lists of pairs: it returns a list of ARRAY references, each one holding two items from the list you gave it. It’s a more efficient version of:

@pairs = pairmap { [ $a, $b ] } @kvlist

It’s most convenient to use in a foreach loop, like this:

foreach my $pair ( pairs @kvlist ) {
   my ( $key, $value ) = @$pair;
   ...
}

Since version 1.39 these ARRAY references are blessed objects, recognising the two methods key and value. The following code is equivalent:

foreach my $pair ( pairs @kvlist ) {
   my $key   = $pair->key;
   my $value = $pair->value;
   ...
}

Since version 1.51 they also have a TO_JSON method to ease serialisation. ✨

unpairs 🌸

my @kvlist = unpairs @pairs

Since version 1.42.

The inverse function to pairs; this function takes a list of ARRAY references containing two elements each, and returns a flattened list of the two values from each of the pairs, in order. This is notionally equivalent to:

my @kvlist = map { @{$_}[0,1] } @pairs

except that it is implemented more efficiently internally. Specifically, for any input item it will extract exactly two values for the output list; using undef if the input array references are short.

Between pairs and unpairs, a higher-order list function can be used to operate on the pairs as single scalars; such as the following near-equivalents of the other pair* higher-order functions:

@kvlist = unpairs grep { FUNC } pairs @kvlist
# Like pairgrep, but takes $_ instead of $a and $b

@kvlist = unpairs map { FUNC } pairs @kvlist
# Like pairmap, but takes $_ instead of $a and $b

Note however that these versions will not behave as nicely in scalar context.

Finally, this technique can be used to implement a sort on a keyvalue pair list; e.g.:

@kvlist = unpairs sort { $a->key cmp $b->key } pairs @kvlist

pairkeys πŸ’–

my @keys = pairkeys @kvlist;

Since version 1.29.

A convenient shortcut to operating on even-sized lists of pairs, this function returns a list of the first values of each of the pairs in the given list. It is a more efficient version of:

@keys = pairmap { $a } @kvlist

pairvalues πŸŽ€

my @values = pairvalues @kvlist;

Since version 1.29.

A convenient shortcut to operating on even-sized lists of pairs, this function returns a list of the second values of each of the pairs in the given list. It is a more efficient version of:

@values = pairmap { $b } @kvlist

pairgrep πŸ¦‹

my @kvlist = pairgrep { BLOCK } @kvlist;

my $count = pairgrep { BLOCK } @kvlist;

Since version 1.29.

Similar to perl’s grep keyword, but interprets the given list as an even-sized list of pairs. It invokes the BLOCK multiple times, in scalar context, with $a and $b set to successive pairs of values from the @kvlist.

Returns an even-sized list of those pairs for which the BLOCK returned true in list context, or the count of the number of pairs in scalar context. (Note, therefore, in scalar context that it returns a number half the size of the count of items it would have returned in list context).

@subset = pairgrep { $a =~ m/^[[:upper:]]+$/ } @kvlist

As with grep aliasing $_ to list elements, pairgrep aliases $a and $b to elements of the given list. Any modifications of it by the code block will be visible to the caller.

pairfirst πŸ‘‘

my ( $key, $val ) = pairfirst { BLOCK } @kvlist;

my $found = pairfirst { BLOCK } @kvlist;

Since version 1.30.

Similar to the first function, but interprets the given list as an even-sized list of pairs. It invokes the BLOCK multiple times, in scalar context, with $a and $b set to successive pairs of values from the @kvlist.

Returns the first pair of values from the list for which the BLOCK returned true in list context, or an empty list if no such pair was found. In scalar context it returns a simple boolean value, rather than either the key or the value found.

( $key, $value ) = pairfirst { $a =~ m/^[[:upper:]]+$/ } @kvlist

As with grep aliasing $_ to list elements, pairfirst aliases $a and $b to elements of the given list. Any modifications of it by the code block will be visible to the caller.

pairmap πŸ”₯

my @list = pairmap { BLOCK } @kvlist;

my $count = pairmap { BLOCK } @kvlist;

Since version 1.29.

Similar to perl’s map keyword, but interprets the given list as an even-sized list of pairs. It invokes the BLOCK multiple times, in list context, with $a and $b set to successive pairs of values from the @kvlist.

Returns the concatenation of all the values returned by the BLOCK in list context, or the count of the number of items that would have been returned in scalar context.

@result = pairmap { "The key $a has value $b" } @kvlist

As with map aliasing $_ to list elements, pairmap aliases $a and $b to elements of the given list. Any modifications of it by the code block will be visible to the caller.

See KNOWN BUGS for a known-bug with pairmap, and a workaround. πŸ’€

✨ OTHER FUNCTIONS ✨

🎲 shuffle

my @values = shuffle @values;

Returns the values of the input in a random order πŸ’…

@cards = shuffle 0..51      # 0..51 in a random order

This function is affected by the $RAND variable.


🎰 sample

my @items = sample $count, @values

Since version 1.54.

Randomly select the given number of elements from the input list. Any given position in the input list will be selected at most once. No cap, it's giving responsible randomization 🫢

If there are fewer than $count items in the list then the function will return once all of them have been randomly selected; effectively the function behaves similarly to shuffle.

This function is affected by the $RAND variable.


🧼 uniq

my @subset = uniq @values

Since version 1.45.

Filters a list of values to remove subsequent duplicates, as judged by a DWIM-ish string equality or undef test. Preserves the order of unique elements, and retains the first value of any duplicate set.

my $count = uniq @values

In scalar context, returns the number of elements that would have been returned as a list.

The undef value is treated by this function as distinct from the empty string, and no warning will be produced. It is left as-is in the returned list. Subsequent undef values are still considered identical to the first, and will be removed. So the first undef is main character energy, and the rest get cut 😭


πŸ”’ uniqint

my @subset = uniqint @values

Since version 1.55.

Filters a list of values to remove subsequent duplicates, as judged by an integer numerical equality test. Preserves the order of unique elements, and retains the first value of any duplicate set. Values in the returned list will be coerced into integers.

my $count = uniqint @values

In scalar context, returns the number of elements that would have been returned as a list.

Note that undef is treated much as other numerical operations treat it; it compares equal to zero but additionally produces a warning if such warnings are enabled (use warnings 'uninitialized';). In addition, an undef in the returned list is coerced into a numerical zero, so that the entire list of values returned by uniqint are well-behaved as integers. Slay, but with a warning πŸ’€


πŸ”’ uniqnum

my @subset = uniqnum @values

Since version 1.44.

Filters a list of values to remove subsequent duplicates, as judged by a numerical equality test. Preserves the order of unique elements, and retains the first value of any duplicate set.

my $count = uniqnum @values

In scalar context, returns the number of elements that would have been returned as a list.

Note that undef is treated much as other numerical operations treat it; it compares equal to zero but additionally produces a warning if such warnings are enabled (use warnings 'uninitialized';). In addition, an undef in the returned list is coerced into a numerical zero, so that the entire list of values returned by uniqnum are well-behaved as numbers.

Note also that multiple IEEE NaN values are treated as duplicates of each other, regardless of any differences in their payloads, and despite the fact that 0+'NaN' == 0+'NaN' yields false. Yes bestie, NaN is messy like that πŸ™ˆ


🧡 uniqstr

my @subset = uniqstr @values

Since version 1.45.

Filters a list of values to remove subsequent duplicates, as judged by a string equality test. Preserves the order of unique elements, and retains the first value of any duplicate set.

my $count = uniqstr @values

In scalar context, returns the number of elements that would have been returned as a list.

Note that undef is treated much as other string operations treat it; it compares equal to the empty string but additionally produces a warning if such warnings are enabled (use warnings 'uninitialized';). In addition, an undef in the returned list is coerced into an empty string, so that the entire list of values returned by uniqstr are well-behaved as strings. String vibe check: passed ✨


my @values = head $size, @list;

Since version 1.50.

Returns the first $size elements from @list. If $size is negative, returns all but the last $size elements from @list.

@result = head 2, qw( foo bar baz );
# foo, bar

@result = head -2, qw( foo bar baz );
# foo

πŸ’ tail

my @values = tail $size, @list;

Since version 1.50.

Returns the last $size elements from @list. If $size is negative, returns all but the first $size elements from @list.

@result = tail 2, qw( foo bar baz );
# bar, baz

@result = tail -2, qw( foo bar baz );
# baz

🌈 List::SomeUtils FUNCTIONS 🌈

🚦 Junctions

πŸ’­ Treatment of an empty list

There are two schools of thought for how to evaluate a junction on an empty list:

  • Reduction to an identity (boolean)
  • Result is undefined (three-valued)

In the first case, the result of the junction applied to the empty list is determined by a mathematical reduction to an identity depending on whether the underlying comparison is or or and. Conceptually:

                       "any are true"      "all are true"
                       --------------      --------------
       2 elements:     A || B || 0         A && B && 1
       1 element:      A || 0              A && 1
       0 elements:     0                   1

In the second case, three-value logic is desired, in which a junction applied to an empty list returns undef rather than true or false.

Junctions with a _u suffix implement three-valued logic. Those without are boolean.


all BLOCK LIST

all_u BLOCK LIST

Returns a true value if all items in LIST meet the criterion given through BLOCK. Sets $_ for each item in LIST in turn:

print "All values are non-negative"
  if all { $_ >= 0 } ($x, $y, $z);

For an empty LIST, all returns true (i.e. no values failed the condition) and all_u returns undef.

Thus, all_u(@list) is equivalent to @list ? all(@list) : undef.

Note: because Perl treats undef as false, you must check the return value of all_u with defined or you will get the opposite result of what you expect. No cap, that's a trap πŸ’€

any BLOCK LIST

any_u BLOCK LIST

Returns a true value if any item in LIST meets the criterion given through BLOCK. Sets $_ for each item in LIST in turn:

print "At least one non-negative value"
  if any { $_ >= 0 } ($x, $y, $z);

For an empty LIST, any returns false and any_u returns undef.

Thus, any_u(@list) is equivalent to @list ? any(@list) : undef.


none BLOCK LIST

none_u BLOCK LIST

Logically the negation of any. Returns a true value if no item in LIST meets the criterion given through BLOCK. Sets $_ for each item in LIST in turn:

print "No non-negative values"
  if none { $_ >= 0 } ($x, $y, $z);

For an empty LIST, none returns true (i.e. no values failed the condition) and none_u returns undef.

Thus, none_u(@list) is equivalent to @list ? none(@list) : undef.

Note: because Perl treats undef as false, you must check the return value of none_u with defined or you will get the opposite result of what you expect. Bestie, defined is the vibe check here 🫢

notall BLOCK LIST

notall_u BLOCK LIST

Logically the negation of all. Returns a true value if not all items in LIST meet the criterion given through BLOCK. Sets $_ for each item in LIST in turn:

print "Not all values are non-negative"
  if notall { $_ >= 0 } ($x, $y, $z);

For an empty LIST, notall returns false and notall_u returns undef.

Thus, notall_u(@list) is equivalent to @list ? notall(@list) : undef.


one BLOCK LIST

one_u BLOCK LIST

Returns a true value if precisely one item in LIST meets the criterion given through BLOCK. Sets $_ for each item in LIST in turn:

print "Precisely one value defined"
    if one { defined($_) } @list;

Returns false otherwise.

For an empty LIST, one returns false and one_u returns undef.

The expression one BLOCK LIST is almost equivalent to 1 == true BLOCK LIST, except for short-cutting. Evaluation of BLOCK will immediately stop at the second true value. It's giving efficient, honestly πŸ”₯


πŸͺ„ Transformation

apply BLOCK LIST

Makes a copy of the list and then passes each element from the copy to the BLOCK. Any changes or assignments to $_ in the BLOCK will only affect the elements of the new list. However, if $_ is a reference then changes to the referenced value will be seen in both the original and new list.

This function is similar to map but will not modify the elements of the input list:

my @list = (1 .. 4);
my @mult = apply { $_ *= 2 } @list;
print "\@list = @list\n";
print "\@mult = @mult\n";
__END__
@list = 1 2 3 4
@mult = 2 4 6 8

Think of it as syntactic sugar for

for (my @mult = @list) { $_ *= 2 }

Note that you must alter $_ directly inside BLOCK in order for changes to make effect. New value returned from the BLOCK are ignored:

# @new is identical to @list.
my @new = apply { $_ * 2 } @list;

# @new is different from @list
my @new = apply { $_ =* 2 } @list;

insert_after BLOCK VALUE LIST

Inserts VALUE after the first item in LIST for which the criterion in BLOCK is true. Sets $_ for each item in LIST in turn.

my @list = qw/This is a list/;
insert_after { $_ eq "a" } "longer" => @list;
print "@list";
__END__
This is a longer list

insert_after_string STRING VALUE LIST

Inserts VALUE after the first item in LIST which is equal to STRING.

my @list = qw/This is a list/;
insert_after_string "a", "longer" => @list;
print "@list";
__END__
This is a longer list

pairwise BLOCK ARRAY1 ARRAY2

Evaluates BLOCK for each pair of elements in ARRAY1 and ARRAY2 and returns a new list consisting of BLOCK's return values. The two elements are set to $a and $b. Note that those two are aliases to the original value so changing them will modify the input arrays. Little gremlin behavior, but make it fashion πŸ’…

@a = (1 .. 5);
@b = (11 .. 15);
@x = pairwise { $a + $b } @a, @b;     # returns 12, 14, 16, 18, 20

# mesh with pairwise
@a = qw/a b c/;
@b = qw/1 2 3/;
@x = pairwise { ($a, $b) } @a, @b;    # returns a, 1, b, 2, c, 3

mesh ARRAY1 ARRAY2 [ ARRAY3 ... ]

zip ARRAY1 ARRAY2 [ ARRAY3 ... ]

Returns a list consisting of the first elements of each array, then the second, then the third, etc, until all arrays are exhausted.

Examples:

@x = qw/a b c d/;
@y = qw/1 2 3 4/;
@z = mesh @x, @y;         # returns a, 1, b, 2, c, 3, d, 4

@a = ('x');
@b = ('1', '2');
@c = qw/zip zap zot/;
@d = mesh @a, @b, @c;   # x, 1, zip, undef, 2, zap, undef, undef, zot

zip is an alias for mesh.


uniq LIST

distinct LIST

Like, here's the deal β€” uniq gives you back a brand-new list with the dupes yeeted, and it does the comparing by treating each value as a hash key. One little plot twist though: undef is treated as totally separate from '' β€” they are not the same girl, they don't share a locker. The order of the elements in the returned list matches LIST exactly, no shuffling. And if you call it in scalar context, you get the count of unique elements in LIST instead. πŸ’…

  my @x = uniq 1, 1, 2, 2, 3, 5, 3, 4; # returns 1 2 3 5 4
  my $x = uniq 1, 1, 2, 2, 3, 5, 3, 4; # returns 5
  # returns "Mike", "Michael", "Richard", "Rick"
  my @n = distinct "Mike", "Michael", "Richard", "Rick", "Michael", "Rick"
  # returns '', undef, 'S1', A5'
  my @s = distinct '', undef, 'S1', 'A5'
  # returns '', undef, 'S1', A5'
  my @w = uniq undef, '', 'S1', 'A5'

distinct is literally just an alias for uniq β€” same energy, different name. 🫢

And if you've got feelings about how this behaves, RT#49800 is the place to spill them.

singleton

Returns a new list by stripping the values in LIST that show up more than once β€” again by comparing values as hash keys, and again with undef treated as separate from ''. Order stays the same as in LIST, obviously. In scalar context it hands you the number of elements that occur only once in LIST. The solo girls, basically. ✨

  my @x = singleton 1,1,2,2,3,4,5 # returns 3 4 5

πŸŽ€ Partitioning πŸŽ€

after BLOCK LIST

Gives you a list of the values of LIST after (and not including) the point where BLOCK goes true. It sets $_ for each element in LIST, one at a time. πŸ¦‹

  @x = after { $_ % 5 == 0 } (1..9);    # returns 6, 7, 8, 9

after_incl BLOCK LIST

Same as after, except it also includes the element where BLOCK was true. Inclusive queen. πŸ‘‘

before BLOCK LIST

Returns a list of values of LIST up to (and not including) the point where BLOCK returns true. Sets $_ for each element in LIST in turn.

before_incl BLOCK LIST

Same as before, but it also includes the element where BLOCK is true.

part BLOCK LIST

Splits LIST into partitions based on what BLOCK returns β€” that return value is literally the "which partition does this value go in" signal. It gives you back a list of the partitions it made, and each partition is an array reference.

  my $i = 0;
  my @part = part { $i++ % 2 } 1 .. 8;   # returns [1, 3, 5, 7], [2, 4, 6, 8]

You can also end up with a sparse list of partitions, where partitions nobody set are just undef:

  my @part = part { 2 } 1 .. 10;            # returns undef, undef, [ 1 .. 10 ]
⚠️ But be careful with negative values, bestie, this is where it gets real:
  my @part = part { -1 } 1 .. 10;
  __END__
  Modification of non-creatable array value attempted, subscript -1 ...

Negative values are only okay when they point at a partition that already exists:

  my @idx  = ( 0, 1, -1 );
  my $i    = 0;
  my @part = part { $idx[$i++ % 3] } 1 .. 8; # [1, 4, 7], [2, 3, 5, 6, 8]

πŸ” Iteration πŸ”

each_array ARRAY1 ARRAY2 ...

Makes an array iterator that hands you the elements of ARRAY1, ARRAY2, all the way through ARRAYn, in turn. So the first time you call it, you get the first element of every array. Next call, the second elements. And so on until all the elements are used up. It's giving synchronized swimming, honestly. πŸŠβ€β™€οΈ

Super useful for looping over more than one array at once, iykyk:

  my $ea = each_array(@a, @b, @c);
  while ( my ($a, $b, $c) = $ea->() )   { .... }

When it hits the end of all the arrays, the iterator returns the empty list.

Oh and β€” if you pass the iterator an argument of "index", it returns the index of the last fetched set of values, as a scalar. Handy!

each_arrayref LIST

Like each_array, but the arguments are references to arrays instead of plain arrays.

natatime EXPR, LIST

Creates an array iterator so you can loop over an array in chunks of $n items at a time. (n at a time β€” get it? πŸ’€). An example explains it way better than words ever could:

Example:

  my @x = ('a' .. 'g');
  my $it = natatime 3, @x;
  while (my @vals = $it->())
  {
    print "@vals\n";
  }

That prints:

  a b c
  d e f
  g

πŸ” Searching πŸ”

bsearch BLOCK LIST

Does a binary search on LIST β€” and LIST must be a sorted list of values, no exceptions, that's the whole bit. BLOCK has to return a negative value if the current element (stored in $_) is smaller, a positive value if it's bigger, and zero if it matches.

In scalar context you get a boolean. In list context you get the element if it was found, otherwise the empty list. 🎯

bsearchidx BLOCK LIST

bsearch_index BLOCK LIST

Does a binary search on LIST, which must be a sorted list of values. BLOCK must return a negative value if the current element (stored in $_) is smaller, a positive value if it's bigger, and zero if it matches.

Returns the index of the found element, otherwise -1.

bsearch_index is an alias for bsearchidx.

firstval BLOCK LIST

first_value BLOCK LIST

Returns the first element in LIST for which BLOCK evaluates to true. Every element of LIST gets set to $_ in turn. Returns undef if nothing matched. πŸ₯Ί

first_value is an alias for firstval.

onlyval BLOCK LIST

only_value BLOCK LIST

Returns the only element in LIST for which BLOCK evaluates to true. Sets $_ for each item in LIST in turn. Returns undef if no such element was found.

only_value is an alias for onlyval.

lastval BLOCK LIST

last_value BLOCK LIST

Returns the last value in LIST for which BLOCK evaluates to true. Each element of LIST gets set to $_ in turn. Returns undef if no such element was found.

last_value is an alias for lastval.

firstres BLOCK LIST

first_result BLOCK LIST

Returns the result of BLOCK for the first element in LIST for which BLOCK evaluates to true. Each element of LIST is set to $_ in turn. Returns undef if no such element has been found.

first_result is an alias for firstres.

onlyres BLOCK LIST

only_result BLOCK LIST

Returns the result of BLOCK for the first element in LIST for which BLOCK evaluates to true. Sets $_ for each item in LIST in turn. Returns undef if no such element has been found.

only_result is an alias for onlyres.

lastres BLOCK LIST

last_result BLOCK LIST

Returns the result of BLOCK for the last element in LIST for which BLOCK evaluates to true. Each element of LIST is set to $_ in turn. Returns undef if no such element has been found.

last_result is an alias for lastres.

indexes BLOCK LIST

Runs BLOCK on every element in LIST (assigned to $_, bestie) and gives you back a list of the indices of the elements where BLOCK went true. It's exactly like grep, except it returns indices instead of values. Glow-up behaviour honestly. 🌈

  @x = indexes { $_ % 2 == 0 } (1..10);   # returns 1, 3, 5, 7, 9

firstidx BLOCK LIST

first_index BLOCK LIST

Returns the index of the first element in LIST where the criterion in BLOCK is true. Sets $_ for each item in LIST in turn:

  my @list = (1, 4, 3, 2, 4, 6);
  printf "item with index %i in list is 4", firstidx { $_ == 4 } @list;
  __END__
  item with index 1 in list is 4

And it returns -1 if no such item could be found.

first_index is an alias for firstidx.

onlyidx BLOCK LIST

only_index BLOCK LIST

Returns the index of the only element in LIST for which the criterion in BLOCK is true. Sets $_ for each item in LIST in turn:

    my @list = (1, 3, 4, 3, 2, 4);
    printf "uniqe index of item 2 in list is %i", onlyidx { $_ == 2 } @list;
    __END__
    unique index of item 2 in list is 4

Returns -1 if either no such item exists or more than one of them was found. Ambiguous? Denied. πŸ™…β€β™€οΈ

only_index is an alias for onlyidx.

lastidx BLOCK LIST

last_index BLOCK LIST

Returns the index of the last element in LIST for which the criterion in BLOCK is true. Sets $_ for each item in LIST in turn:

  my @list = (1, 4, 3, 2, 4, 6);
  printf "item with index %i in list is 4", lastidx { $_ == 4 } @list;
  __END__
  item with index 4 in list is 4

Returns -1 if no such item could be found.

last_index is an alias for lastidx.


🚦 Sorting 🚦

sort_by BLOCK LIST

Returns the list of values sorted according to the string values returned by the KEYFUNC block or function. A classic use of this is sorting objects by the string value of some accessor, like:

  sort_by { $_->name } @people

The key function gets called in scalar context and is passed each value in turn as both $_ and the only argument in the parameters, @_. Then the values get sorted by string comparisons on whatever the function returned. It's equivalent to:

  sort { $a->name cmp $b->name } @people

…except sort_by guarantees the name accessor only runs once per value. Efficient! Obsessed. ✨

One kinda iconic use-case: sorting strings with numbers embedded in them "naturally" instead of lexically.

  sort_by { s/(\d+)/sprintf "%09d", $1/eg; $_ } @strings

That sorts strings by generating sort keys which zero-pad the embedded numbers to some level (9 digits in this case) so the lexical sort actually puts them in the right order. Big brain moment. 🧠

nsort_by BLOCK LIST

Just like sort_by, except it compares its key values numerically.


πŸ”’ Counting and calculation πŸ”’

true BLOCK LIST

Counts how many elements in LIST have the criterion in BLOCK come out true. Sets $_ for each item in LIST in turn:

  printf "%i item(s) are defined", true { defined($_) } @list;

false BLOCK LIST

Counts how many elements in LIST have the criterion in BLOCK come out false. Sets $_ for each item in LIST in turn:

  printf "%i item(s) are not defined", false { defined($_) } @list;

minmax LIST

Works out the minimum and maximum of LIST and returns a two-element list β€” first element is the minimum, second is the maximum. If LIST was empty, you get the empty list back.

Now here's the tea β˜•: the minmax algorithm is not the same as a naive iteration over the list where you compare each element to two running values (the so-far min and max). It only needs 3n/2 - 2 comparisons, making it the most efficient possible algorithm. Periodt.

πŸ™ˆ But heads up β€” the Perl implementation of it has some overhead just because there are more lines of Perl code involved. So LIST needs to be reasonably big for minmax to actually beat a naive implementation. That limitation does not apply to the XS version, though. πŸ’…

mode LIST

Calculates the most common items in the list and returns them as a list. It does this effectively by string comparisons, so references get stringified β€” and if they implement string overloading, that gets used.

If more than one item appears the same number of times, all of those items get returned. For example, the mode of a unique list is the list itself. Slay.

This function returns a list in list context. In scalar context it returns a count indicating the number of modes in the list. πŸ“

πŸ’… List::UtilsBy FUNCTIONS

okay bestie, heads up before we dive in: every single one of these functions was added in version 0.04 or later unless it says otherwise, because the OG names from the earlier versions got renamed. just so you know what's what 🫢

sort_by

@vals = sort_by { KEYFUNC } @vals

Gives you back the list sorted by the string values that the KEYFUNC block (or function) spits out. the classic move is sorting your objects by some accessor's string value, like:

sort_by { $_->name } @people

The key function gets called in scalar context, and each value gets passed in twice β€” once as $_ and once as the sole argument in @_. then everything gets sorted by string comparisons (cmp vibes) on whatever the function returned ✨

This does exactly what

sort { $a->name cmp $b->name } @people

does, EXCEPT it guarantees your name accessor only runs once per value. no cap, that's the whole selling point πŸ’…

One kinda iconic use-case: sorting strings that have numbers buried in them "naturally" instead of lexically. like:

sort_by { s/(\d+)/sprintf "%09d", $1/eg; $_ } @strings

That one works by generating sort keys that zero-pad the embedded numbers up to some level (9 digits here), which helps make sure the lexical sort actually lands them in the right order. chef's kiss πŸŽ€

nsort_by

@vals = nsort_by { KEYFUNC } @vals

sort_by's sibling, except it compares the key values numerically instead of as strings. same energy, different comparison πŸ”₯

rev_sort_by and rev_nsort_by

@vals = rev_sort_by { KEYFUNC } @vals

@vals = rev_nsort_by { KEYFUNC } @vals

Since version 0.06, bestie πŸ’–

They're like sort_by and nsort_by but they hand you back the list in reverse order. equivalent to:

@vals = reverse sort_by { KEYFUNC } @vals

except these two are a tiny bit more efficient because they skip that final reverse step. small gains, still gains πŸ’€

max_by

$optimal = max_by { KEYFUNC } @vals

@optimal = max_by { KEYFUNC } @vals

Returns the value from @vals that gives the numerically largest result from the key function. (technically it returns the first such value, keep that in mind πŸ‘€)

my $tallest = max_by { $_->height } @people

use File::stat qw( stat );
my $newest = max_by { stat($_)->mtime } @files;

In scalar context you get the first maximal value. In list context you get a list of all the maximal values β€” which is lowkey useful when you want to grab positions other than the first one, if order matters to you.

If you call it on an empty list, you get an empty list back. no drama 🌸

And for symmetry with nsort_by, it's also available under the name nmax_by, since it behaves numerically. two names, one legend πŸ‘‘

min_by

$optimal = min_by { KEYFUNC } @vals

@optimal = min_by { KEYFUNC } @vals

Just like max_by but it returns the values giving the numerically smallest result from the key function. Also provided as nmin_by πŸ¦‹

minmax_by

( $minimal, $maximal ) = minmax_by { KEYFUNC } @vals

Since version 0.11 ✨

Basically what you'd get from calling both min_by and max_by with the same key function on the same list β€” but this version is more efficient than calling the two separately, because it's got less work to do overall. when there's a tie, it only returns the first optimal element it finds in each case. Also provided as nminmax_by 🫢

uniq_by

@vals = uniq_by { KEYFUNC } @vals

Returns the subset of values whose key function returned unique values. The first value that yields a particular key wins; everything after it gets rejected, periodt πŸ’…

my @some_fruit = uniq_by { $_->colour } @fruit;

Want the last value per key instead? reverse the input list. and if the order of the results matters to you, don't forget to reverse the result too:

my @some_fruit = reverse uniq_by { $_->colour } reverse @fruit;
⚠️ because the key function's return values get used as hash keys, they should either be strings, or at least be well-behaved as strings β€” like numbers, or object references that overload stringification in a sensible way. don't come crying to me if your keys are weird 😭

partition_by

%parts = partition_by { KEYFUNC } @vals

Hands you a key/value list of ARRAY refs, with all the original values distributed according to what the key function returned. Each value is an ARRAY ref containing every value that returned that string from the key function, keeping their original order. it's giving organized πŸŽ€

my %balls_by_colour = partition_by { $_->colour } @balls;
⚠️ same warning as before: those return values are hash keys, so they ought to be strings or at least string-well-behaved (numbers, overloaded-object refs, you know the drill).

count_by

%counts = count_by { KEYFUNC } @vals

Since version 0.07 πŸ¦‹

Returns a key/value list of integers β€” how many times the key function returned that key, for every value in the list. like a little census for your list, ngl:

my %count_of_balls = count_by { $_->colour } @balls;
⚠️ yep, same rule: hash keys, so keep them string-ish or string-well-behaved.

zip_by

@vals = zip_by { ITEMFUNC } \@arr0, \@arr1, \@arr2,...

Returns a list of everything the function block gave back when called with values pulled from across each of the given ARRAY references. Every value in the returned list is the result of calling the function with the arguments sitting at that position, across all the arrays you passed in. it's a zipper, bestie 🧚

my @transposition = zip_by { [ @_ ] } @matrix;

my @names = zip_by { "$_[1], $_[0]" } \@firstnames, \@surnames;

print zip_by { "$_[0] => $_[1]\n" } [ keys %hash ], [ values %hash ];

If some of the arrays are shorter than the others, the function just acts like they had undef in those trailing positions. these two lines are literally equivalent:

zip_by { f(@_) } [ 1, 2, 3 ], [ "a", "b" ]
f( 1, "a" ), f( 2, "b" ), f( 3, undef )

The item function gets called by map, so if it returns a list, the entire list lands in the result. super handy for building a hash out of 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 with this behaviour is sometimes called "zipWith", like in Haskell β€” but that name wouldn't fit the naming scheme this module's got going on, so πŸ’€)

unzip_by

$arr0, $arr1, $arr2, ... = unzip_by { ITEMFUNC } @vals

Since version 0.09 🌈

Returns a list of ARRAY references containing the values the function block returned, when invoked for each of the values in the input list. Each returned ARRAY ref holds the values returned at that corresponding position by the function block β€” so the first returned ARRAY ref has all the values from the first position, the second has all the values from the second position, and so on forever.

my ( $firstnames, $lastnames ) = unzip_by { m/^(.*?) (.*)$/ } @names;

If the function returns lists of different lengths, the result gets padded with undef in the missing slots. no gaps left behind 🫢

This function is the inverse of zip_by β€” as long as you give it a corresponding inverse function, obviously.

extract_by

@vals = extract_by { SELECTFUNC } @arr

Since version 0.05 πŸ‘‘

Removes elements from the referenced array that the selection function returns true for, and returns a list of those elements. It's like grep, except it modifies the referenced array β€” yanking the selected values out and leaving only the unselected ones behind.

my @red_balls = extract_by { $_->color eq "red" } @balls;

# Now there are no red balls in the @balls array
⚠️ heads up: this function modifies a real array, unlike pretty much everything else in this module. Because of that, it needs an actual array β€” not just a list, bestie.

It's implemented by calling splice on the array, NOT by building a new list and assigning it over. One consequence of that (and it's a big one): weak references won't be disturbed πŸ’…

extract_by { !defined $_ } @refs;

That will leave the weak references in @refs still weakened, whereas

@refs = grep { defined $_ } @refs;

will strengthen them all again. subtle, but iconic.

extract_first_by

$val = extract_first_by { SELECTFUNC } @arr

Since version 0.10 πŸŽ€

A little hybrid of extract_by and List::Util::first. It removes the first element from the referenced array that the selection function returns true for, and returns it.

Same deal as extract_by: it needs a real array and not just a list, and it's also implemented using splice so weak references don't get disturbed. 😀

If it can't find a matching element, it returns an empty list in list context β€” which lets a caller tell the difference between "no matching element at all" and "the first matching element happened to literally be undef". sneaky but smart.

weighted_shuffle_by

@vals = weighted_shuffle_by { WEIGHTFUNC } @vals

Since version 0.07 πŸ¦‹

Returns the list of values shuffled into a random order β€” except the randomization isn't uniform, it's weighted by whatever WEIGHTFUNC returns. The probability of each item coming back first is distributed according to the distribution of the weights, and then recursively the same for all the items left over 🌸

bundle_by

@vals = bundle_by { BLOCKFUNC } $number, @vals

Since version 0.07 πŸ’œ

Similar to a regular map, basically: returns a list of the values BLOCKFUNC gave back, with values from the input list handed to the block function in bundles of $number.

If the list's length doesn't divide evenly by $number, that final call just gets passed fewer elements than the others. leftovers are still invited to the party, they just get a smaller plate πŸ“


πŸ›οΈ EXPORTS

This module exports nothing by default. zero, zip, nada. You import functions by name, or grab everything with the :all tag. iykyk πŸ’…


πŸ‘€ SEE ALSO

List::Util, List::SomeUtils and List::UtilsBy, obviously. like, duh 😭

Also peep Util::Any, which unifies a whole bunch more util modules, and also lets you rename functions as part of the import. fancy 🌟


πŸ› BUGS

Please report any bugs or feature requests to bug-list-allutils@rt.cpan.org, or through the web interface at http://rt.cpan.org. I'll get notified, and then you'll automatically get notified of progress on your bug as I make changes. teamwork, bestie 🫢

Bugs may also be submitted at https://github.com/houseabsolute/List-AllUtils/issues.

I'm also usually active on IRC as 'autarch' on irc://irc.perl.org. come say hi πŸ’–


πŸ“‚ SOURCE

The source code repository for List-AllUtils can be found at https://github.com/houseabsolute/List-AllUtils. go touch grass, or the code, whichever 🌈

πŸ’– DONATIONS πŸ’–

okay so if you're feeling generous and wanna thank Dave for all the work he's put into this module, he'd love it if you considered making a "donation" via PayPal. he spends a lot of his free time making free software, and honestly? any support you feel like offering would be super appreciated 🫢

okay but real talk, before you open your wallet: he's not saying you must donate for him to keep working on this particular software. he'll keep at it, same as he always has, for as long as it interests him. no pressure, bestie, fr fr πŸ’…

and also, like, a donation made this way will probably not make him work on this software much more, unless he gets so many donations that he can consider working on free software full time β€” and like, let's all have a chuckle at that together πŸ˜­πŸ’€

to donate, log into PayPal and send money to autarch@urth.org, or use the button at https://www.urth.org/fs-donation.html.


✨ AUTHOR ✨

Dave Rolsky <autarch@urth.org> πŸ‘‘


πŸ¦‹ CONTRIBUTORS πŸ¦‹

the supporting cast, the besties, the ones who helped make this iconic:

  • Andy Jack <github@veracity.ca>
  • Dave Jacoby <jacoby.david@gmail.com>
  • Karen Etheridge <ether@cpan.org>
  • Olaf Alders <olaf@wundersolutions.com>
  • Ricardo Signes <rjbs@cpan.org>
  • Yanick Champoux <yanick@babyl.dyndns.org>

This software is Copyright (c) 2021 by Dave Rolsky.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)

The full text of the license can be found in the LICENSE file included with this distribution. go read it, it's right there, no cap πŸ“œβœ¨


and that's a wrap on the whole page, bestie πŸŽ‰ version perl v5.42.0, dated 2021-04-24, List::AllUtils(3) β€” go forth and reduce some lists, you absolute icon πŸŒΈπŸ«ΆπŸ’œ

πŸ“¦ where this page comes from