=encoding utf8
=head1 NAME
list/util - List utility functions.
=head1 SYNOPSIS
from list/util import grep, head, map, sortnum_by, sum, ListUtil;
say( sum( [ 10, 20, 30 ] ) );
let users := [
{ name: "Zoe", age: 32, score: 87, active: true },
{ name: "Ada", age: 41, score: 98, active: true },
{ name: "Max", age: 27, score: 91, active: false },
{ name: "Bea", age: 36, score: 93, active: true },
];
let by_name := ListUtil.sortstr_by( users, fn user → user{name} );
let oldest := ListUtil.max_by( users, fn user → user{age} );
let leaderboard := users
▷ grep( ^^, fn user → user{active} )
▷ sortnum_by( ^^, fn user → user{score} )
▷ reverse( ^^ )
▷ head( ^^, 3 )
▷ map( ^^, fn user → user{name} );
say( leaderboard ); // Ada, Bea, Zoe
=head1 DESCRIPTION
This pure-Zuzu module provides functions inspired by Perl's
C<List::Util>, C<List::MoreUtils>, and C<List::UtilsBy>. Functions are
exported directly, and the C<ListUtil> class provides static wrappers
for code that wants to avoid importing many names.
Most functions take the collection first. Predicate callbacks receive
one value. Reducer callbacks receive C<(accumulator, value)>. Key
callbacks for C<*_by> functions receive one value and are called once
per input value. Pair callbacks receive a Zuzu C<Pair> object.
=head2 Collection Support
C<Array> is the primary input type.
C<Bag> and C<Set> are accepted by order-insensitive functions. Their
iteration order is the order returned by the runtime's C<to_Array>
method and should not be treated as stable unless the runtime documents
it.
Ordered and position-sensitive functions require C<Array>. Pair helpers
which operate on pairs expect an C<Array> of C<Pair> objects.
=head1 FUNCTIONS
=head2 Reduction
=over
=item C<< reduce(Array values, Function callback) >>
Calls C<callback(accumulator, value)> from left to right. Returns
C<null> for an empty array.
reduce( [ 1, 2, 3 ], fn ( a, b ) → a + b ); // 6
=item C<< reductions(Array values, Function callback) >>
Returns every intermediate accumulator value.
reductions( [ 1, 2, 3 ], fn ( a, b ) → a + b ); // [ 1, 3, 6 ]
=back
=head2 Predicates And Searches
=over
=item C<< any(Array|Bag|Set values, Function predicate) >>
Returns true if any value satisfies C<predicate(value)>.
any( [ 1, 2, 3 ], fn x → x > 2 ); // true
=item C<< all(Array|Bag|Set values, Function predicate) >>
Returns true if every value satisfies C<predicate(value)>.
all( [ 2, 4, 6 ], fn x → x mod 2 = 0 ); // true
=item C<< none(Array|Bag|Set values, Function predicate) >>
Returns true if no value satisfies C<predicate(value)>.
none( [ 1, 3, 5 ], fn x → x mod 2 = 0 ); // true
=item C<< notall(Array|Bag|Set values, Function predicate) >>
Returns true if at least one value does not satisfy C<predicate(value)>.
notall( [ 2, 4, 5 ], fn x → x mod 2 = 0 ); // true
=item C<< first(Array values, Function predicate) >>
Returns the first matching value, or C<null>.
first( [ 1, 2, 3 ], fn x → x > 1 ); // 2
=item C<< firstval(Array values, Function predicate) >>
Alias-style helper equivalent to C<first>.
firstval( [ "a", "bb" ], fn x → length(x) > 1 ); // "bb"
=item C<< firstidx(Array values, Function predicate) >>
Returns the first matching index, or C<-1>.
firstidx( [ 1, 4, 9 ], fn x → x > 3 ); // 1
=item C<< lastval(Array values, Function predicate) >>
Returns the last matching value, or C<null>.
lastval( [ 1, 4, 9 ], fn x → x > 3 ); // 9
=item C<< lastidx(Array values, Function predicate) >>
Returns the last matching index, or C<-1>.
lastidx( [ 1, 4, 9 ], fn x → x > 3 ); // 2
=item C<< onlyval(Array|Bag|Set values, Function predicate) >>
Returns the value if exactly one value matches, otherwise C<null>.
onlyval( [ 1, 2, 3 ], fn x → x = 2 ); // 2
=item C<< onlyidx(Array values, Function predicate) >>
Returns the index if exactly one value matches, otherwise C<-1>.
onlyidx( [ 1, 2, 3 ], fn x → x = 2 ); // 1
=back
=head2 Numeric And String Values
=over
=item C<< max(Array|Bag|Set values) >>
Returns the numerically greatest value, or C<null>.
max( [ 7, 2, 10 ] ); // 10
=item C<< min(Array|Bag|Set values) >>
Returns the numerically smallest value, or C<null>.
min( [ 7, 2, 10 ] ); // 2
=item C<< maxstr(Array|Bag|Set values) >>
Returns the string-greatest value, or C<null>.
maxstr( [ "b", "aa" ] ); // "b"
=item C<< minstr(Array|Bag|Set values) >>
Returns the string-smallest value, or C<null>.
minstr( [ "b", "aa" ] ); // "aa"
=item C<< sum(Array|Bag|Set values) >>
Returns the numeric sum, or C<null> for an empty collection.
sum( [ 1, "2", 3 ] ); // 6
=item C<< sum0(Array|Bag|Set values) >>
Returns the numeric sum, using C<0> for an empty collection.
sum0( [] ); // 0
=item C<< product(Array|Bag|Set values) >>
Returns the numeric product, using C<1> for an empty collection.
product( [ 2, "3", 4 ] ); // 24
=back
=head2 Pairs
=over
=item C<< pairs(Array flat) >>
Converts a flat key/value array into an array of C<Pair> objects.
pairs( [ "a", 1, "b", 2 ] );
=item C<< unpairs(Array pair_objects) >>
Converts an array of C<Pair> objects into a flat key/value array.
unpairs( pairs( [ "a", 1 ] ) ); // [ "a", 1 ]
=item C<< pairkeys(Array pair_objects) >>
Returns pair keys.
pairkeys( pairs( [ "a", 1, "b", 2 ] ) ); // [ "a", "b" ]
=item C<< pairvalues(Array pair_objects) >>
Returns pair values.
pairvalues( pairs( [ "a", 1, "b", 2 ] ) ); // [ 1, 2 ]
=item C<< pairfirst(Array pair_objects, Function predicate) >>
Returns the first C<Pair> where C<predicate(pair)> is true, or C<null>.
pairfirst( pairs( [ "a", 1 ] ), fn p → p.key eq "a" );
=item C<< pairgrep(Array pair_objects, Function predicate) >>
Returns all C<Pair> objects where C<predicate(pair)> is true.
pairgrep( pairs( [ "a", 1, "b", 2 ] ), fn p → p.value > 1 );
=item C<< pairmap(Array pair_objects, Function mapper) >>
Maps each C<Pair> using C<mapper(pair)>.
pairmap( pairs( [ "a", 1 ] ), fn p → p.key _ "=" _ p.value );
=back
=head2 Ordering And Uniqueness
=over
=item C<< sort(Array values, Function comparator) >>
Returns a sorted array using C<comparator(left, right)>.
sort( [ 1, 3, 2 ], fn ( a, b ) → a ≶ b ); // [ 1, 2, 3 ]
=item C<< sortnum(Array|Bag|Set values) >>
Returns values sorted numerically.
sortnum( [ "2", "10", "1" ] ); // [ "1", "2", "10" ]
=item C<< sortstr(Array|Bag|Set values) >>
Returns values sorted stringwise.
sortstr( [ "b", "aa" ] ); // [ "aa", "b" ]
=item C<< reverse(Array|Bag|Set values) >>
Returns values in reverse order.
reverse( [ 1, 2, 3 ] ); // [ 3, 2, 1 ]
=item C<< map(Array|Bag|Set values, Function mapper) >>
Returns C<mapper(value)> for each value.
map( [ 1, 2, 3 ], fn x → x × 2 ); // [ 2, 4, 6 ]
=item C<< grep(Array|Bag|Set values, Function predicate) >>
Returns values where C<predicate(value)> is true.
grep( [ 1, 2, 3 ], fn x → x > 1 ); // [ 2, 3 ]
=item C<< shuffle(Array|Bag|Set values) >>
Returns the values in random order.
shuffle( [ 1, 2, 3 ] );
=item C<< sample(Array|Bag|Set values, Number count) >>
Returns up to C<count> random values in random order, without
replacement. If C<count> is larger than the input collection, all values
are returned in random order.
sample( [ 1, 2, 3 ], 2 );
=item C<< uniq(Array|Bag|Set values) >>
Returns first-seen unique values using Zuzu equality.
uniq( [ 1, 1, 2 ] ); // [ 1, 2 ]
=item C<< uniqint(Array|Bag|Set values) >>
Returns first-seen values unique by integer value.
uniqint( [ 1.1, 1.9, 2.1 ] ); // [ 1.1, 2.1 ]
=item C<< uniqnum(Array|Bag|Set values) >>
Returns first-seen values unique by numeric value.
uniqnum( [ "1", 1, 2 ] ); // [ "1", 2 ]
=item C<< uniqstr(Array|Bag|Set values) >>
Returns first-seen values unique by string value.
uniqstr( [ 1, "1", 2 ] ); // [ 1, 2 ]
=item C<< head(Array values, Number count := 1) >>
Returns the first C<count> values.
head( [ 1, 2, 3 ], 2 ); // [ 1, 2 ]
=item C<< tail(Array values, Number count := 1) >>
Returns the last C<count> values.
tail( [ 1, 2, 3 ], 2 ); // [ 2, 3 ]
=item C<< zip(Array first, Array second, ...) >>
Returns rows formed from the given arrays, using C<null> where an input
array is short.
zip( [ "a", "b" ], [ 1, 2 ] ); // [ [ "a", 1 ], [ "b", 2 ] ]
=item C<< mesh(Array first, Array second, ...) >>
Returns the same values as C<zip>, flattened.
mesh( [ "a", "b" ], [ 1, 2 ] ); // [ "a", 1, "b", 2 ]
=back
=head2 Keyed Helpers
=over
=item C<< sort_by(Array|Bag|Set values, Function key_function) >>
Sorts values numerically by C<key_function(value)>. The key function is
called once per value, using a Schwartzian transform.
sort_by( users, fn user → user{age} );
=item C<< sortnum_by(Array|Bag|Set values, Function key_function) >>
Alias for C<sort_by>.
sortnum_by( users, fn user → user{age} );
=item C<< sortstr_by(Array|Bag|Set values, Function key_function) >>
Sorts values stringwise by C<key_function(value)>.
sortstr_by( users, fn user → user{name} );
=item C<< max_by(Array|Bag|Set values, Function key_function) >>
Returns the value with the greatest numeric key. The key function is
called once per value.
max_by( users, fn user → user{age} );
=item C<< maxnum_by(Array|Bag|Set values, Function key_function) >>
Alias for C<max_by>.
maxnum_by( users, fn user → user{age} );
=item C<< maxstr_by(Array|Bag|Set values, Function key_function) >>
Returns the value with the greatest string key.
maxstr_by( users, fn user → user{name} );
=item C<< min_by(Array|Bag|Set values, Function key_function) >>
Returns the value with the smallest numeric key. The key function is
called once per value.
min_by( users, fn user → user{age} );
=item C<< minnum_by(Array|Bag|Set values, Function key_function) >>
Alias for C<min_by>.
minnum_by( users, fn user → user{age} );
=item C<< minstr_by(Array|Bag|Set values, Function key_function) >>
Returns the value with the smallest string key.
minstr_by( users, fn user → user{name} );
=item C<< uniq_by(Array|Bag|Set values, Function key_function) >>
Returns first-seen values unique by string key. The key function is
called once per value.
uniq_by( users, fn user → user{name} );
=back
=head1 CLASS
=head2 C<ListUtil>
C<ListUtil> provides every exported function as a static method with
the same signature.
from list/util import ListUtil;
say( ListUtil.sum( [ 1, 2, 3 ] ) );
=head1 COPYRIGHT AND LICENCE
B<< list/util >> is copyright Toby Inkster.
It is free software; you may redistribute it and/or modify it under
the terms of either the Artistic License 1.0 or the GNU General Public
License version 2.
=cut
function _ordered_array ( values, String name ) {
if ( typeof values ne "Array" ) {
die name _ " expects an Array";
}
return values;
}
function _collection_array ( values, String name ) {
if ( typeof values eq "Array" ) {
return values;
}
if ( typeof values eq "Bag" ⋁ typeof values eq "Set" ) {
return values.to_Array;
}
die name _ " expects an Array, Bag, or Set";
}
function _pair_array ( values, String name ) {
let out := _ordered_array( values, name );
for ( let pair in out ) {
if ( ¬ ( pair instanceof Pair ) ) {
die name _ " expects an Array of Pair objects";
}
}
return out;
}
function _key_string ( value ) {
return "" _ value;
}
function _key_number ( value ) {
return 0 + value;
}
function _key_integer ( value ) {
return int(value);
}
function _array_contains_value ( Array values, value ) {
for ( let existing in values ) {
return true if existing ≡ value;
}
return false;
}
function _array_contains_key ( Array keys, key ) {
for ( let existing in keys ) {
return true if existing eq key;
}
return false;
}
function reduce ( values, Function callback ) {
let items := _ordered_array( values, "reduce" );
return null if items.empty;
let accumulator := items[0];
let i := 1;
while ( i < items.length ) {
accumulator := callback( accumulator, items[i] );
i++;
}
return accumulator;
}
function reductions ( values, Function callback ) {
let items := _ordered_array( values, "reductions" );
let out := [];
return out if items.empty;
let accumulator := items[0];
out.push(accumulator);
let i := 1;
while ( i < items.length ) {
accumulator := callback( accumulator, items[i] );
out.push(accumulator);
i++;
}
return out;
}
function any ( values, Function predicate ) {
for ( let value in _collection_array( values, "any" ) ) {
return true if predicate(value);
}
return false;
}
function all ( values, Function predicate ) {
for ( let value in _collection_array( values, "all" ) ) {
return false if ¬ predicate(value);
}
return true;
}
function none ( values, Function predicate ) {
return ¬ any( values, predicate );
}
function notall ( values, Function predicate ) {
return ¬ all( values, predicate );
}
function first ( values, Function predicate ) {
for ( let value in _ordered_array( values, "first" ) ) {
return value if predicate(value);
}
return null;
}
function max ( values ) {
let items := _collection_array( values, "max" );
return null if items.empty;
let best := items[0];
let i := 1;
while ( i < items.length ) {
best := items[i] if _key_number( items[i] ) > _key_number(best);
i++;
}
return best;
}
function maxstr ( values ) {
let items := _collection_array( values, "maxstr" );
return null if items.empty;
let best := items[0];
let i := 1;
while ( i < items.length ) {
best := items[i] if _key_string( items[i] ) gt _key_string(best);
i++;
}
return best;
}
function min ( values ) {
let items := _collection_array( values, "min" );
return null if items.empty;
let best := items[0];
let i := 1;
while ( i < items.length ) {
best := items[i] if _key_number( items[i] ) < _key_number(best);
i++;
}
return best;
}
function minstr ( values ) {
let items := _collection_array( values, "minstr" );
return null if items.empty;
let best := items[0];
let i := 1;
while ( i < items.length ) {
best := items[i] if _key_string( items[i] ) lt _key_string(best);
i++;
}
return best;
}
function product ( values ) {
let total := 1;
for ( let value in _collection_array( values, "product" ) ) {
total ×= _key_number(value);
}
return total;
}
function sum ( values ) {
let items := _collection_array( values, "sum" );
return null if items.empty;
let total := 0;
for ( let value in items ) {
total += _key_number(value);
}
return total;
}
function sum0 ( values ) {
let total := 0;
for ( let value in _collection_array( values, "sum0" ) ) {
total += _key_number(value);
}
return total;
}
function pairs ( values ) {
let items := _ordered_array( values, "pairs" );
let out := [];
let i := 0;
while ( i < items.length ) {
out.push(
new Pair(
pair: [
items[i],
i + 1 < items.length ? items[i + 1] : null,
],
),
);
i += 2;
}
return out;
}
function unpairs ( values ) {
let out := [];
for ( let pair in _pair_array( values, "unpairs" ) ) {
out.push( pair.key );
out.push( pair.value );
}
return out;
}
function pairkeys ( values ) {
return _pair_array( values, "pairkeys" ).map( fn p → p.key );
}
function pairvalues ( values ) {
return _pair_array( values, "pairvalues" ).map( fn p → p.value );
}
function pairfirst ( values, Function predicate ) {
for ( let pair in _pair_array( values, "pairfirst" ) ) {
return pair if predicate(pair);
}
return null;
}
function pairgrep ( values, Function predicate ) {
let out := [];
for ( let pair in _pair_array( values, "pairgrep" ) ) {
out.push(pair) if predicate(pair);
}
return out;
}
function pairmap ( values, Function mapper ) {
let out := [];
for ( let pair in _pair_array( values, "pairmap" ) ) {
out.push( mapper(pair) );
}
return out;
}
function sort ( values, Function comparator ) {
return _ordered_array( values, "sort" ).sort(comparator);
}
function sortnum ( values ) {
return _collection_array( values, "sortnum" ).sortnum;
}
function sortstr ( values ) {
return _collection_array( values, "sortstr" ).sortstr;
}
function reverse ( values ) {
return _collection_array( values, "reverse" ).reverse;
}
function map ( values, Function mapper ) {
let out := [];
for ( let value in _collection_array( values, "map" ) ) {
out.push( mapper(value) );
}
return out;
}
function grep ( values, Function predicate ) {
let out := [];
for ( let value in _collection_array( values, "grep" ) ) {
out.push(value) if predicate(value);
}
return out;
}
function shuffle ( values ) {
return _collection_array( values, "shuffle" ).shuffle;
}
function sample ( values, Number count ) {
let shuffled := _collection_array( values, "sample" ).shuffle;
let limit := count < 0 ? 0 : count;
limit := shuffled.length if limit > shuffled.length;
let out := [];
let i := 0;
while ( i < limit ) {
out.push( shuffled[i] );
i++;
}
return out;
}
function uniq ( values ) {
let out := [];
for ( let value in _collection_array( values, "uniq" ) ) {
out.push(value) if ¬ _array_contains_value( out, value );
}
return out;
}
function _uniq_by_key ( values, Function key_function, String name ) {
let out := [];
let keys := [];
for ( let value in _collection_array( values, name ) ) {
let key := _key_string( key_function(value) );
if ( ¬ _array_contains_key( keys, key ) ) {
keys.push(key);
out.push(value);
}
}
return out;
}
function uniqint ( values ) {
return _uniq_by_key( values, fn value → _key_integer(value), "uniqint" );
}
function uniqnum ( values ) {
return _uniq_by_key( values, fn value → _key_number(value), "uniqnum" );
}
function uniqstr ( values ) {
return _uniq_by_key( values, fn value → _key_string(value), "uniqstr" );
}
function head ( values, Number count := 1 ) {
let items := _ordered_array( values, "head" );
let out := [];
let limit := count > items.length ? items.length : count;
let i := 0;
while ( i < limit ) {
out.push( items[i] );
i++;
}
return out;
}
function tail ( values, Number count := 1 ) {
let items := _ordered_array( values, "tail" );
let start := items.length - count;
start := 0 if start < 0;
let out := [];
let i := start;
while ( i < items.length ) {
out.push( items[i] );
i++;
}
return out;
}
function _validate_zip_inputs ( Array lists, String name ) {
for ( let list in lists ) {
if ( typeof list ne "Array" ) {
die name _ " expects Array arguments";
}
}
return lists;
}
function _zip_lists ( Array lists ) {
_validate_zip_inputs( lists, "zip" );
let max_length := 0;
for ( let list in lists ) {
max_length := list.length if list.length > max_length;
}
let out := [];
let i := 0;
while ( i < max_length ) {
let row := [];
for ( let list in lists ) {
row.push( i < list.length ? list[i] : null );
}
out.push(row);
i++;
}
return out;
}
function zip ( ... lists ) {
return _zip_lists(lists);
}
function mesh ( ... lists ) {
_validate_zip_inputs( lists, "mesh" );
let out := [];
for ( let row in _zip_lists(lists) ) {
for ( let value in row ) {
out.push(value);
}
}
return out;
}
function firstval ( values, Function predicate ) {
for ( let value in _ordered_array( values, "firstval" ) ) {
return value if predicate(value);
}
return null;
}
function firstidx ( values, Function predicate ) {
let items := _ordered_array( values, "firstidx" );
let i := 0;
while ( i < items.length ) {
return i if predicate( items[i] );
i++;
}
return -1;
}
function lastval ( values, Function predicate ) {
let items := _ordered_array( values, "lastval" );
let i := items.length - 1;
while ( i ≥ 0 ) {
return items[i] if predicate( items[i] );
i--;
}
return null;
}
function lastidx ( values, Function predicate ) {
let items := _ordered_array( values, "lastidx" );
let i := items.length - 1;
while ( i ≥ 0 ) {
return i if predicate( items[i] );
i--;
}
return -1;
}
function onlyval ( values, Function predicate ) {
let found := false;
let match := null;
for ( let value in _collection_array( values, "onlyval" ) ) {
if ( predicate(value) ) {
return null if found;
found := true;
match := value;
}
}
return found ? match : null;
}
function onlyidx ( values, Function predicate ) {
let items := _ordered_array( values, "onlyidx" );
let found := false;
let match := -1;
let i := 0;
while ( i < items.length ) {
if ( predicate( items[i] ) ) {
return -1 if found;
found := true;
match := i;
}
i++;
}
return match;
}
function _sort_by_key ( values, Function key_function, String name, String mode ) {
let decorated := [];
let i := 0;
for ( let value in _collection_array( values, name ) ) {
let raw_key := key_function(value);
decorated.push(
{
key: mode eq "number" ? _key_number(raw_key) : _key_string(raw_key),
index: i,
value: value,
},
);
i++;
}
return decorated.sort( function ( left, right ) {
let comparison := mode eq "number"
? left{key} ≶ right{key}
: left{key} cmp right{key};
return comparison if comparison ≠ 0;
return left{index} ≶ right{index};
} ).map( fn row → row{value} );
}
function sort_by ( values, Function key_function ) {
return _sort_by_key( values, key_function, "sort_by", "number" );
}
function sortnum_by ( values, Function key_function ) {
return sort_by( values, key_function );
}
function sortstr_by ( values, Function key_function ) {
return _sort_by_key( values, key_function, "sortstr_by", "string" );
}
function max_by ( values, Function key_function ) {
let items := _collection_array( values, "max_by" );
return null if items.empty;
let best := items[0];
let best_key := _key_number( key_function(best) );
let i := 1;
while ( i < items.length ) {
let value := items[i];
let key := _key_number( key_function(value) );
if ( key > best_key ) {
best := value;
best_key := key;
}
i++;
}
return best;
}
function maxnum_by ( values, Function key_function ) {
return max_by( values, key_function );
}
function maxstr_by ( values, Function key_function ) {
let items := _collection_array( values, "maxstr_by" );
return null if items.empty;
let best := items[0];
let best_key := _key_string( key_function(best) );
let i := 1;
while ( i < items.length ) {
let value := items[i];
let key := _key_string( key_function(value) );
if ( key gt best_key ) {
best := value;
best_key := key;
}
i++;
}
return best;
}
function min_by ( values, Function key_function ) {
let items := _collection_array( values, "min_by" );
return null if items.empty;
let best := items[0];
let best_key := _key_number( key_function(best) );
let i := 1;
while ( i < items.length ) {
let value := items[i];
let key := _key_number( key_function(value) );
if ( key < best_key ) {
best := value;
best_key := key;
}
i++;
}
return best;
}
function minnum_by ( values, Function key_function ) {
return min_by( values, key_function );
}
function minstr_by ( values, Function key_function ) {
let items := _collection_array( values, "minstr_by" );
return null if items.empty;
let best := items[0];
let best_key := _key_string( key_function(best) );
let i := 1;
while ( i < items.length ) {
let value := items[i];
let key := _key_string( key_function(value) );
if ( key lt best_key ) {
best := value;
best_key := key;
}
i++;
}
return best;
}
function uniq_by ( values, Function key_function ) {
return _uniq_by_key( values, key_function, "uniq_by" );
}
class ListUtil {
static method reduce ( values, Function callback ) {
return reduce( values, callback );
}
static method reductions ( values, Function callback ) {
return reductions( values, callback );
}
static method any ( values, Function predicate ) {
return any( values, predicate );
}
static method all ( values, Function predicate ) {
return all( values, predicate );
}
static method none ( values, Function predicate ) {
return none( values, predicate );
}
static method notall ( values, Function predicate ) {
return notall( values, predicate );
}
static method first ( values, Function predicate ) {
return first( values, predicate );
}
static method max ( values ) {
return max(values);
}
static method maxstr ( values ) {
return maxstr(values);
}
static method min ( values ) {
return min(values);
}
static method minstr ( values ) {
return minstr(values);
}
static method product ( values ) {
return product(values);
}
static method sum ( values ) {
return sum(values);
}
static method sum0 ( values ) {
return sum0(values);
}
static method pairs ( values ) {
return pairs(values);
}
static method unpairs ( values ) {
return unpairs(values);
}
static method pairkeys ( values ) {
return pairkeys(values);
}
static method pairvalues ( values ) {
return pairvalues(values);
}
static method pairfirst ( values, Function predicate ) {
return pairfirst( values, predicate );
}
static method pairgrep ( values, Function predicate ) {
return pairgrep( values, predicate );
}
static method pairmap ( values, Function mapper ) {
return pairmap( values, mapper );
}
static method sort ( values, Function comparator ) {
return sort( values, comparator );
}
static method sortnum ( values ) {
return sortnum(values);
}
static method sortstr ( values ) {
return sortstr(values);
}
static method reverse ( values ) {
return reverse(values);
}
static method map ( values, Function mapper ) {
return map( values, mapper );
}
static method grep ( values, Function predicate ) {
return grep( values, predicate );
}
static method shuffle ( values ) {
return shuffle(values);
}
static method sample ( values, Number count ) {
return sample( values, count );
}
static method uniq ( values ) {
return uniq(values);
}
static method uniqint ( values ) {
return uniqint(values);
}
static method uniqnum ( values ) {
return uniqnum(values);
}
static method uniqstr ( values ) {
return uniqstr(values);
}
static method head ( values, Number count := 1 ) {
return head( values, count );
}
static method tail ( values, Number count := 1 ) {
return tail( values, count );
}
static method zip ( ... lists ) {
return _zip_lists(lists);
}
static method mesh ( ... lists ) {
let out := [];
for ( let row in _zip_lists(lists) ) {
for ( let value in row ) {
out.push(value);
}
}
return out;
}
static method firstval ( values, Function predicate ) {
return firstval( values, predicate );
}
static method firstidx ( values, Function predicate ) {
return firstidx( values, predicate );
}
static method lastval ( values, Function predicate ) {
return lastval( values, predicate );
}
static method lastidx ( values, Function predicate ) {
return lastidx( values, predicate );
}
static method onlyval ( values, Function predicate ) {
return onlyval( values, predicate );
}
static method onlyidx ( values, Function predicate ) {
return onlyidx( values, predicate );
}
static method sort_by ( values, Function key_function ) {
return sort_by( values, key_function );
}
static method sortnum_by ( values, Function key_function ) {
return sortnum_by( values, key_function );
}
static method sortstr_by ( values, Function key_function ) {
return sortstr_by( values, key_function );
}
static method max_by ( values, Function key_function ) {
return max_by( values, key_function );
}
static method maxnum_by ( values, Function key_function ) {
return maxnum_by( values, key_function );
}
static method maxstr_by ( values, Function key_function ) {
return maxstr_by( values, key_function );
}
static method min_by ( values, Function key_function ) {
return min_by( values, key_function );
}
static method minnum_by ( values, Function key_function ) {
return minnum_by( values, key_function );
}
static method minstr_by ( values, Function key_function ) {
return minstr_by( values, key_function );
}
static method uniq_by ( values, Function key_function ) {
return uniq_by( values, key_function );
}
}
modules/list/util.zzm
list-util-0.0.1 source code
Package
- Name
- list-util
- Version
- 0.0.1
- Uploaded
- 2026-05-28 09:57:26
- Metadata
- zuzu-distribution.json
- Archive
- Download .tar.gz