Skip to content
Classroom

Array Macros

Working with arrays and lists in question control code.

Most PHP array functions are not available

Control code runs against a fixed allowlist. array_push, array_pop, array_shift, array_unshift, array_slice, array_search, array_key_exists, array_merge, sort, asort and rsort are not on it. Earlier versions of this page documented all of them. The engine's own equivalents are below.

Creating arrays

array($value1, $value2, …)

$colors = array("red", "green", "blue")
$numbers = array(1, 2, 3, 4, 5)
$person = array("name" => "Alice", "age" => 25)

Bracket shorthand works too

$colors = ["red", "green"] and $person = ["name" => "Alice", "age" => 25] create the same arrays as array(...). Either form can be passed straight to a macro, e.g. sumarray([3, 5, 8]).

consecutive($min, $max, $step)

A run of evenly spaced values — the engine's range constructor. $step defaults to 1 and may be negative to count down.

$ints = consecutive(1, 10)          // 1, 2, 3, … 10
$evens = consecutive(2, 20, 2)      // 2, 4, 6, … 20
$down = consecutive(10, 1, -1)      // 10, 9, 8, … 1
$tenths = calconarray(consecutive(0, 10), "x/10")   // 0, 0.1, 0.2, … 1 exactly
// consecutive(0, 1, 0.1) drifts: its last value is 0.9999999999999999, so == 1 fails

fillarray($value, $n, $start)

$n copies of $value, keyed from $start (default 0). If $n is itself an array, its entries become the keys.

$zeros = fillarray(0, 5)                              // five 0s
$blanks = fillarray("", array("a", "b"))              // "a" => "", "b" => ""

listtoarray($list) and stringtoarray($str)

listtoarray splits a comma-separated string and trims each piece. stringtoarray splits into individual bytes, which are characters only for plain ASCII text — a character such as π or ² is split into broken pieces.

$colors = listtoarray("red, blue, green")   // "red", "blue", "green"
$chars = stringtoarray("abc")               // "a", "b", "c"

Reading arrays

Indexing works as expected, and count, in_array, is_array, array_keys, array_values, array_reverse, array_unique, array_flip and isset are all allowlisted native functions.

$colors = array("red", "green", "blue")
$first = $colors[0]          // "red"
$total = count($colors)      // 3

$person = array("name" => "Alice", "age" => 25)
$name = $person["name"]      // "Alice"

Use isset, not array_key_exists

array_key_exists is not allowlisted. isset($person["email"]) does the same job for question code.

arrayfindindex($needle, $haystack)

The key of the first matching value.

Needle first, haystack second

The reverse of the argument order the old page showed. It returns the key, or false when the value is absent — so compare with !== false, not >= 0.

$i = arrayfindindex("green", $colors)   // 1

arrayfindindices($needle, $haystack) returns all matching keys.

sumarray($array)

Adds the elements. Errors if given a non-array.

$total = sumarray(array(3, 5, 8))   // 16

arrayhasduplicates($array)

true when any value repeats — useful for asserting that generated distractors are distinct.

$bad = arrayhasduplicates($choices)

Reordering and reshaping

sortarray($array, $direction, $maxkey)

Returns a sorted copy — it does not sort in place. If the first element is numeric the whole array sorts numerically (non-numeric strings count as 0); otherwise PHP's default comparison is used, which still compares numeric strings as numbers.

$direction Effect
omitted ascending
"rev" descending
"key" sort by key rather than value
"keyfill" fill gaps in the keys with "" up to $maxkey, then sort by key
$sorted = sortarray(array(5, 2, 9))          // 2, 5, 9
$desc = sortarray(array(5, 2, 9), "rev")     // 9, 5, 2

splicearray($array, $offset, $length, $replacement)

The engine's one editing macro — it covers everything array_push, array_pop, array_shift, array_unshift and array_slice did, and returns a new array.

$nums = array(1, 2, 3)

$appended = splicearray($nums, count($nums), 0, array(4))   // add to the end
$prepended = splicearray($nums, 0, 0, array(0))             // add to the front
$dropfirst = splicearray($nums, 0, 1)                       // remove the front
$droplast = splicearray($nums, -1, 1)                       // remove the end
$middle = splicearray($nums, 1, 1)                          // remove index 1

To read the value you removed, index it before splicing:

$last = $nums[count($nums) - 1]
$nums = splicearray($nums, -1, 1)

subarray($array, $indices…)

Picks out selected positions. Each argument is an index, or a "start:end" range string (inclusive).

$picked = subarray($nums, 0, 2)        // elements 0 and 2
$range = subarray($nums, "1:2")        // elements 1 and 2 (inclusive)

Combining arrays

Macro Returns
mergearrays($a1, $a2, …) all elements, concatenated; non-array arguments are wrapped
unionarrays($a1, $a2) elements of $a1 plus those of $a2 not already present
intersectarrays($a1, $a2) elements present in both
diffarrays($a1, $a2) elements of $a1 not in $a2
$all = mergearrays(array(1, 2), array(3, 4))     // 1, 2, 3, 4
$common = intersectarrays($a, $b)

Calculating across an array

Macro Purpose
calconarray($array, $todo) apply an expression to every element
calconarrayif($array, $todo, $ifcond) apply it only where a condition holds
multicalconarray() apply across several arrays at once
keepif($array, $todo) keep only elements satisfying a condition
arraysetvalues($arr, $keys, $values) set several keys at once
jointsort() sort several arrays by the first one's order

jointsort is the sorting counterpart to jointshuffle — use it when values and their labels live in parallel arrays and must stay aligned.

Turning arrays into text

joinarray($array, $separator, $ksort) and arraytolist($array, $spaced) are documented on the String Macros page. There is no implode.

$list = joinarray($colors, ", ")   // "red, green, blue"

Interpolating an array prints Array

"Colors: $colors" renders the literal word Array. Join it first.

Examples

Build randomized multiple-choice options that stay aligned

$opts = array("3", "5", "7", "9")
$fb   = array("no", "no", "yes", "no")
$opts,$fb = jointshuffle($opts, $fb)
$correct = arrayfindindex("yes", $fb)

Generate a data set and summarize it

$data = rands(10, 40, 8)
$data = sortarray($data)
$n = count($data)
$total = sumarray($data)
$mean = $total / $n

Reject a draw that repeats

$choices = randsfrom($pool, 4) where (arrayhasduplicates($choices) == false)

diffrandsfrom($pool, 4) does the same thing directly and is preferred — see Randomizers.

See Also