-
Notifications
You must be signed in to change notification settings - Fork 0
List Operations
skLambda can run a lambda across a whole list for you (transforming, folding, sorting, or picking an extreme element) so you don't have to write the loop yourself.
Each of these takes a list on the left and a lambda on the right. See Lambdas for how to make those.
For filtering, counting, and finding a list with a predicate, you don't need a special skLambda expression. Skript's own where, number of, and first element of already do it. See Filter, count, and find with a predicate below.
Changed in 1.1.1. skLambda used to ship its own
%list% filtered where … passes,count of %list% where … passes, andfirst of %list% where … passes. Those duplicated what Skript core already provides, so they were removed. Combine a predicate with Skript's built-in filter instead, as shown below. The lambda forms (mapped with,reduced with,sorted by,highest/lowest of … by) are unchanged.
mapped with runs a one-argument lambda on each element and gives back a new list the same size. Each element is replaced by what the lambda returns.
set {_double} to lambda (n: number) -> number:
return {_n} * 2
set {_doubled::*} to (3, 5, 2) mapped with {_double}
# {_doubled::*} is 6, 10, 4You can also write mapped using or mapped through. If the lambda returns nothing for an element, that element is dropped.
reduced with combines a list down to a single value using a two-argument lambda. It goes left to right: the first argument is the running result (the accumulator), the second is the next element.
set {_add} to lambda (a: number, b: number) -> number:
return {_a} + {_b}
set {_total} to (3, 5, 2) reduced with {_add}
# add(3, 5) = 8, then add(8, 2) = 10 -> {_total} is 10A one-element list reduces to that element (the lambda never runs). An empty list reduces to nothing. You can also write reduced using.
If the lambda returns nothing for a step, that step is skipped and the running result carries on unchanged. Before 1.5.0 the nothing was carried forward as the accumulator, which silently reset the fold partway through. scanned with behaves the same way.
%list% reduced with %lambda% from %start% sets what the running result begins at. Now the lambda runs once for every element, so the first call combines the start value with element 1.
set {_total} to (3, 5, 2) reduced with {_add} from 100
# add(100, 3) = 103, add(103, 5) = 108, add(108, 2) = 110 -> {_total} is 110Two things this gives you:
- An empty list safely returns the start value instead of nothing.
- The start can be a different type than the elements, for example folding a list of items down into one piece of text.
Added in 1.1.0.
scanned with is like reduced with, but instead of only the final value it keeps every running result along the way. You get back a list, not a single value.
set {_add} to lambda (a: number, b: number) -> number:
return {_a} + {_b}
set {_running::*} to (3, 5, 2) scanned with {_add}
# 3, then add(3, 5) = 8, then add(8, 2) = 10 -> {_running::*} is 3, 8, 10%list% scanned with %lambda% from %start% opens from a seed. The seed comes out first, then one result per element.
set {_running::*} to (3, 5, 2) scanned with {_add} from 100
# 100, add(100, 3) = 103, add(103, 5) = 108, add(108, 2) = 110 -> 100, 103, 108, 110Handy for running balances and cumulative totals. Added in 1.2.0.
zipped with … using walks two lists in lockstep and combines each pair with a two-argument lambda. The first argument is the element from the left list, the second from the right.
set {_add} to lambda (a: number, b: number) -> number:
return {_a} + {_b}
set {_summed::*} to (1, 2, 3) zipped with (10, 20, 30) using {_add}
# add(1, 10) = 11, add(2, 20) = 22, add(3, 30) = 33 -> 11, 22, 33It stops at the shorter list, so pairing a three-element list with a five-element one gives three results. Added in 1.2.0.
sorted by orders a list using a lambda that pulls a sort key out of each element. The lambda runs once per element and returns something comparable like a number or text. The list comes back ordered by those keys, lowest first.
set {_score} to lambda (p: player) -> number:
return {_p}'s level
set {_ranked::*} to all players sorted by {_score}
# players ordered by level, lowest firstThe sort is stable: elements with equal keys keep their original relative order.
Changed in 1.5.0. Elements whose lambda returns nothing now sink to the end, and keys of different kinds are grouped by kind. Before, one missing or odd key was enough to make the sort a no-op on the whole list, and sorting by a text key never ordered anything at all.
highest of … by and lowest of … by give you back the single element with the biggest (or smallest) key. You write a lambda that scores each element, and you get the winning element itself, not the score.
set {_score} to lambda (p: player) -> number:
return {_p}'s level
set {_top} to highest of all players by {_score} # the highest-level player
set {_bottom} to lowest of all players by {_score} # the lowest-level playerYou can write max for highest and min for lowest. Ties keep the first one found; an empty list gives nothing. This is cheaper than sorting the whole list when you only want the one extreme element.
Added in 1.1.0.
These cut a list into pieces of a fixed size S, with no lambda needed. They're built for paging a list into a GUI.
page N of %list% by S splits the list into back-to-back chunks of S and hands you the Nth one (1-based). The last page can be shorter, and a page past the end is empty.
set {_items::*} to "a", "b", "c", "d", "e", "f", and "g"
set {_p1::*} to page 1 of {_items::*} by 3 # a, b, c
set {_p2::*} to page 2 of {_items::*} by 3 # d, e, f
set {_p3::*} to page 3 of {_items::*} by 3 # gwindow N of %list% by S is like a page, but it slides one element at a time instead of jumping a whole chunk. Window 1 is elements 1 to S, window 2 is elements 2 to S+1, and so on.
set {_w1::*} to window 1 of {_items::*} by 3 # a, b, c
set {_w2::*} to window 2 of {_items::*} by 3 # b, c, dpage count of %list% by S is how many pages the list splits into, rounded up so a partial last page still counts. window count of %list% by S is length - S + 1. Loop over the count to fill a menu.
set {_pages} to page count of {_items::*} by 3 # 3 (7 items -> 3, 3, 1)
set {_windows} to window count of {_items::*} by 3 # 5 (7 - 3 + 1)
loop (page count of {_items::*} by 3) times:
set {_page::*} to page loop-value of {_items::*} by 3
# ... build GUI page loop-value from {_page::*}Added in 1.2.0.
taken while and dropped while cut a list at the first element that fails a predicate. Unlike a filter, they depend on position, which is exactly why Skript's where can't express them: where tests every element independently, these stop at the first "no".
set {_positive} to lambda (n: number): {_n} > 0
set {_prefix::*} to (5, 3, 1, -2, 4) taken while {_positive} passes # 5, 3, 1
set {_rest::*} to (5, 3, 1, -2, 4) dropped while {_positive} passes # -2, 4Note the 4 at the end stays dropped even though it's positive: once the run is broken at -2, everything after it belongs to the remainder.
The two always partition the list, so joining them back together rebuilds the original. The edges follow from that:
| List | taken while |
dropped while |
|---|---|---|
| first element already fails | empty | the whole list |
| every element passes | the whole list | empty |
A lambda that returns anything other than true counts as not passing, so it ends the run. To filter regardless of position, use Skript's where instead (below).
Added in 1.4.0.
skLambda has no dedicated filter, count, or first expression, since Skript core already gives you all three. Pair a predicate with Skript's built-in filter using the input keyword, which stands for the element being tested.
Filter: keep only the elements the predicate passes for, with Skript's %list% where [...]:
set {_big} to lambda (n: number): {_n} > 3
set {_kept::*} to (3, 5, 2, 8) where [{_big} passes for input]
# {_kept::*} is 5, 8Count: wrap that filter in Skript's number of:
set {_n} to number of ({_players::*} where [{_is-op} passes for input])First: wrap it in Skript's first element of. Skript stops at the first match, so it's cheap:
set {_winner} to first element of ({_players::*} where [{_alive} passes for input])A predicate list works too: [{_checks::*} passes for input] keeps an element only if all of them pass, the same all-of rule as a bare passes check. For "doesn't match", reach for a negated predicate.
These three used to have skLambda spellings (
filtered where … passes,count of … where … passes,first of … where … passes); they were removed in 1.1.1 as duplicates of Skript core. Thewhere [... passes for input]form above replaces all of them.
| Operation | Gives back | Lambda it takes |
|---|---|---|
%list% mapped with %lambda% |
a new list, same size | 1-arg value lambda |
%list% reduced with %lambda% [from %start%] |
one value | 2-arg lambda |
%list% scanned with %lambda% [from %start%] |
a new list of running results | 2-arg lambda |
%list% zipped with %list2% using %lambda% |
a new list, length of the shorter | 2-arg lambda |
highest of %list% by %lambda% (max) |
one element | 1-arg key lambda |
lowest of %list% by %lambda% (min) |
one element | 1-arg key lambda |
%list% sorted by %lambda% |
the list, reordered | 1-arg key lambda |
%list% taken while %predicate% passes |
the leading run that passes | 1-arg predicate |
%list% dropped while %predicate% passes |
everything from the first failure on | 1-arg predicate |
For filtering, counting, and finding, use Skript's own list tools with a predicate (see above):
| Want | Skript core + predicate |
|---|---|
| keep matching elements | %list% where [%predicate% passes for input] |
| how many match | number of (%list% where [%predicate% passes for input]) |
| the first match | first element of (%list% where [%predicate% passes for input]) |
Paging takes no lambda, just a chunk size:
| Want | Expression |
|---|---|
| the Nth non-overlapping chunk | page N of %list% by S |
| the Nth sliding window | window N of %list% by S |
| how many pages | page count of %list% by S |
| how many windows | window count of %list% by S |
For full working examples, see Examples.
Guides
Reference





