Module:UtilsTable

From Zelda Wiki, the Zelda encyclopedia
Jump to navigation Jump to search

Utility library for operating on Lua tables. Inspired by Lodash.

Note that the array functions in this module are not designed to process "sparse arrays" such as {1, nil, 3} or {nil, 2, 3}. The only exceptions are compact and padNils, which transform sparse arrays into "dense" ones.

Some functions have two variants: a "normal" procedural programming variant, and a functional programming variant of the same name but prefixed with _. The latter functions are curried and iteratee-first data-last as in lodash/fp. This is useful for composition. For example,

Input Function Output
local games = {
  {
    initialism = "TMC",
    subtitle = "The Minish Cap",
  },
  {
    initialism = "TWW",
    subtitle = "The Wind Waker",
  },
  {
    initialism = "TP",
    subtitle = "Twilight Princess",
  },
}
Without UtilsWith UtilsWith Utils (Functional)
local result = {}
for _, game in ipairs(games) do
  if string.sub(game.subtitle, 1, 3) == "The" then
    table.insert(result, game.subtitle)
  end
end
return result
local result = games
result = utilsTable.map(result, "subtitle")
result = utilsTable.filter(result, utilsString._startsWith("The")) 
return result
return utilsFunction.pipe(games) {
  utilsTable._map("subtitle"),
  utilsTable._filter(utilsString._startsWith("The")),
}
{"The Minish Cap", "The Wind Waker"}

The above example is somewhat contrived for the sake of simplicity. In real contexts, use whichever utility function results in the greatest readability. Sometimes the best option will be to forgo these utilities in favor of plain for-loops.

This module exports the following functions.

Tables

clone

clone(tbl)

Returns

  • Creates a shallow clone of tbl.

Examples

#InputOutputResult
1
local original = { foo = {} }
local clone = utilsTable.clone(original)
return {
  clone,
  original ~= clone, 
  original.foo == clone.foo,
}
{
  {
    foo = {},
  },
  true,
  true,
}
Green check.svg

cloneDeep

cloneDeep(tbl)

Similar to mw.clone except that it differs in how it handles metatables.

Returns

  • Creates a recursive clone of tbl.

Examples

#InputOutputResult
2
local original = { foo = {} }
local clone = utilsTable.cloneDeep(original)
return {
  clone,
  original ~= clone, 
  original.foo ~= clone.foo,
}
{
  {
    foo = {},
  },
  true,
  true,
}
Green check.svg

hasArray

hasArray(tbl)

Returns

  • True if the table contains integer keys (or is empty).

Examples

#InputOutputResult
3
hasArray({1, 2, 3})
true
Green check.svg
4
hasArray({})
true
Green check.svg
5
hasArray({ foo = "bar" })
false
Green check.svg
6
hasArray({"baz", foo = "bar"})
true
Green check.svg

hasKey

hasKey_hasKey

hasKey(tbl, key)

Returns

  • True if tbl[key] is not nil, else false.

Examples

#InputOutputResult
7
hasKey({"foo", [3] = "bar"}, 3)
true
Green check.svg
8
hasKey(
  {
    baz = "quux",
    foo = "bar",
  },
  "baz"
)
true
Green check.svg
9
hasKey({"foo", "bar"}, 3)
false
Green check.svg
10
hasKey(
  {
    baz = "b",
    foo = "a",
  },
  "quux"
)
false
Green check.svg

_hasKey(tbl)

Returns

  • True if tbl[key] is not nil, else false.

Examples

#InputOutputResult
11
_hasKey(3)({"foo", [3] = "bar"})
true
Green check.svg
12
_hasKey("baz")({
  foo = "bar",
  baz = "quux",
})
true
Green check.svg
13
_hasKey(3)({"foo", "bar"})
false
Green check.svg
14
_hasKey("quux")({
  foo = "a",
  baz = "b",
})
false
Green check.svg

invert

invert(tbl)

Returns

  • A table with the values of tbl as its keys, and vice-versa.

Examples

#InputOutputResult
15
invert({"foo", "bar", baz = "quux"})
{
  quux = "baz",
  bar = 2,
  foo = 1,
}
Green check.svg
Values will be overwritten if tbl has duplicate values. Overwrite order is not guaranteeed.
16
invert({
  Ganon = "Power",
  Link = "Courage",
  Zelda = "Wisdom",
  Ganondorf = "Power",
})
{
  Wisdom = "Zelda",
  Courage = "Link",
  Power = "Ganondorf",
}
Green check.svg

isArray

isArray(tbl)

Returns

  • True if the table contains only integer keys (or is empty).

Examples

#InputOutputResult
17
isArray({1, 2, 3})
true
Green check.svg
18
isArray({})
true
Green check.svg
19
isArray({[3] = "foo" })
true
Green check.svg
20
isArray({ [10] = "foo" })
true
Green check.svg
21
isArray({ foo = "bar" })
false
Green check.svg
22
isArray({"baz", foo = "bar"})
false
Green check.svg

isEmpty

isEmpty(tbl)

Returns

  • True if tbl has no keys whatsoever

Examples

#InputOutputResult
23
isEmpty({})
true
Green check.svg
24
isEmpty({ foo = "bar" })
false
Green check.svg
25
isEmpty({[2] = "foo" })
false
Green check.svg

isEqual

isEqual_isEqual

isEqual(tbl, other)

Returns

  • true if tbl deep equals other.

Examples

#InputOutputResult
26
isEqual(
  {
    foo = { bar = "baz" },
  },
  {
    foo = { bar = "baz" },
  }
)
true
Green check.svg
27
isEqual(
  {
    foo = { bar = "baz" },
  },
  {
    foo = { bar = "quux" },
  }
)
false
Green check.svg

_isEqual(other)

Returns

  • true if tbl deep equals other.

Examples

#InputOutputResult
28
_isEqual({
  foo = { bar = "baz" },
})({
  foo = { bar = "baz" },
})
true
Green check.svg
29
_isEqual({
  foo = { bar = "baz" },
})({
  foo = { bar = "quux" },
})
false
Green check.svg

isMatch

isMatch_isMatch

isMatch(tbl, source)

Performs a partial deep comparison between tbl and other to determine if tbl contains equivalent values.

Returns

  • Returns true if tbl is a match, else false

Examples

#InputOutputResult
30
isMatch(
  {
    foo = {
      flip = "flop",
      bar = "baz",
    },
  },
  {
    foo = { bar = "baz" },
  }
)
true
Green check.svg
31
isMatch({1, 2, 3}, {1, 2})
true
Green check.svg
32
isMatch(
  {
    foo = { bar = "baz" },
  },
  {
    foo = { bar = "quux" },
  }
)
false
Green check.svg

_isMatch(tbl)

Performs a partial deep comparison between tbl and other to determine if tbl contains equivalent values.

Returns

  • Returns true if tbl is a match, else false

Examples

#InputOutputResult
33
_isMatch({
  foo = { bar = "baz" },
})({
  foo = {
    bar = "baz",
    flip = "flop",
  },
})
true
Green check.svg
34
_isMatch({1, 2})({1, 2, 3})
true
Green check.svg
35
_isMatch({
  foo = { bar = "quux" },
})({
  foo = { bar = "baz" },
})
false
Green check.svg

ivalues

ivalues(tbl)

Returns

  • Array of contiguous, integer-keyed values in tbl starting from 1.

Examples

#InputOutputResult
36
ivalues({
  "foo",
  "bar",
  [10] = "baz",
  wibble = "wobble",
})
{"foo", "bar"}
Green check.svg

keyOf

keyOf(tbl, value)

Returns

  • First key found whose value is shallow-equal to value, or nil if none found.

Examples

#InputOutputStatus
37
keyOf({"foo", [3] = "bar"}, "bar")
3
Green check.svg
38
keyOf(
  {
    baz = "quux",
    foo = "bar",
  },
  "quux"
)
"baz"
Green check.svg
39
keyOf({"foo", "bar"}, "quux")
nil
Green check.svg
Does not perform deep-equal checks on tables.
40
keyOf(
  {
    {},
    {},
  },
  {}
)
nil
Green check.svg

keys

keys(tbl)

See also values and stringKeys.

Returns

  • Array of tbl keys.

Examples

#InputOutputResult
41
keys({"foo", "bar", "baz"})
{1, 2, 3}
Green check.svg
42
keys({
  foo = "bar",
  baz = "quux",
})
{"foo", "baz"}
Green check.svg
43
keys({"foo", [3] = "quux", bar = "baz"})
{1, 3, "bar"}
Green check.svg

mapValues

mapValues(tbl, iteratee)

Returns

  • Creates a table with the same keys as tbl and values generated by running each value of tbl thru iteratee.

Examples

#InputOutputResult
44
local templateArgs = {
  arg1 = "  foo ",
  arg2 = "bar\n",
}
return utilsTable.mapValues(templateArgs, mw.text.trim)
{
  arg2 = "bar",
  arg1 = "foo",
}
Green check.svg
property shorthand
45
mapValues(
  {
    Zelda = { Triforce = "Wisdom" },
    Link = { Triforce = "Courage" },
  },
  "Triforce"
)
{
  Link = "Courage",
  Zelda = "Wisdom",
}
Green check.svg

merge

merge(tbl, ...)

Recursively merges tables.

Returns

  • tbl with merged values. Subsequent sources overwrite key assignments of previous sources.

Examples

#InputOutputResult
46
local tbl = {
  flib = "flob",
  foo = {
    bar = {"flib", "flob"},
    baz = {"quux", "quuz"},
  },
}
utilsTable.merge(tbl, {
  foo = {
    bar = {"noot"},
    baz = "noot",
    wibble = "wobble",
  },
})
return tbl
{
  flib = "flob",
  foo = {
    wibble = "wobble",
    baz = "noot",
    bar = {"noot", "flob"},
  },
}
Green check.svg
Common use: merging keys into new table.
47
merge({}, { flib = "flob" }, { wibble = "wobble" })
{
  flib = "flob",
  wibble = "wobble",
}
Green check.svg

print

print(tbl, [singleLine])

Parameters

Returns

  • tbl pretty-printed as a string.

Examples

#InputOutputStatus
Prints array items on a single line.
48
print({"foo", "bar", "baz"})
'{"foo", "bar", "baz"}'
Green check.svg
Prints single line when tables has one string key.
49
print({ foo = "bar" })
'{ foo = "bar" }'
Green check.svg
50
print({1, 2, 3, foo = "bar"})
'{1, 2, 3, foo = "bar"}'
Green check.svg
Prints one value per line if more than one string key.
51
print({
  flib = "flub",
  foo = "bar",
})
'{\n  flib = "flub",\n  foo = "bar",\n}'
Green check.svg
52
print({
  1,
  2,
  3,
  flib = "flub",
  foo = "bar",
})
'{\n  1,\n  2,\n  3,\n  flib = "flub",\n  foo = "bar",\n}'
Green check.svg
Prints one value per line if any are tables.
53
print({
  {1},
  {2},
})
"{\n  {1},\n  {2},\n}"
Green check.svg
Prints one value per line if single-line would exceed 50 characters.
54
print({
  "abcdefghijklmnopqrstuvwxyz",
  "abcdefghijklmnopqrstuvwxyz",
})
'{\n  "abcdefghijklmnopqrstuvwxyz",\n  "abcdefghijklmnopqrstuvwxyz",\n}'
Green check.svg
Always prints single-line when singleLine is true
55
print(
  {
    "abcdefghijklmnopqrstuvwxyz",
    "abcdefghijklmnopqrstuvwxyz",
  },
  true
)
'{"abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"}'
Green check.svg

printPath

printPath(path)

Returns

  • Property path as a string.

Examples

#InputOutputStatus
56
printPath({"foo", 1, "bar", 1})
".foo[1].bar[1]"
Green check.svg
57
printPath({"foo", '["bar"]'})
'.foo["bar"]'
Green check.svg

property

property_property

property(tbl, path)

Returns

  • The value at path for tbl.

Examples

#InputOutputStatus
58
property(
  {
    foo = {"bar"},
  },
  {"foo", 1}
)
"bar"
Green check.svg
59
property(
  {
    foo = {"bar"},
  },
  {"foo", "bar", "baz"}
)
nil
Green check.svg

_property(tbl)

Returns

  • The value at path for tbl.

Examples

#InputOutputStatus
60
_property({"foo", 1})({
  foo = {"bar"},
})
"bar"
Green check.svg
61
_property({"foo", "bar", "baz"})({
  foo = {"bar"},
})
nil
Green check.svg

size

size(tbl)

Returns

  • Total number of keys in tbl.

Examples

#InputOutputResult
62
size({1, 2, foo = "bar"})
3
Green check.svg

stringKeys

stringKeys(tbl)

Returns

  • Array of string keys in tbl

Examples

#InputOutputResult
63
stringKeys({
  1,
  2,
  [true] = false,
  foo = "bar",
})
{"foo"}
Green check.svg

toArray

toArray_toArray

toArray(tbl, [keys], [padValue])

Parameters

Returns

  • An array of all the values in tbl. Order not guaranteed unless keys is specified. If so, the returned array is such that array[i] = utilsTable.keyOf(keys, tbl[i]). Note that the function will return a sparse array when tbl[i] == nil.

Examples

#InputOutputResult
Order not guaranteed.
64
toArray({
  a = "foo",
  c = true,
  b = 2,
})
{"foo", true, 2}
Green check.svg
keys param can be used to specify order.
65
toArray(
  {
    a = "foo",
    c = true,
    b = 2,
  },
  {"c", "a", "b"}
)
{true, "foo", 2}
Green check.svg
keys param can be used to grab a subset of the keys.
66
toArray(
  {
    a = "foo",
    c = true,
    b = 2,
  },
  {"a", "b"}
)
{"foo", 2}
Green check.svg
keys param can result in a sparse array if key not in tbl.
67
toArray(
  {
    a = "foo",
    c = true,
    b = 2,
  },
  {"b", "a", "d", "c"}
)
{2, "foo", [4] = true}
Green check.svg
Sparse arrays can be padded with a custom padValue.
68
toArray(
  {
    a = "foo",
    c = true,
    b = 2,
  },
  {"b", "a", "d", "c"},
  ""
)
{2, "foo", "", true}
Green check.svg

_toArray(tbl)

Parameters

Returns

  • An array of all the values in tbl. Order not guaranteed unless keys is specified. If so, the returned array is such that array[i] = utilsTable.keyOf(keys, tbl[i]). Note that the function will return a sparse array when tbl[i] == nil.

Examples

#InputOutputResult
Order not guaranteed.
69
_toArray()({
  a = "foo",
  c = true,
  b = 2,
})
{"foo", true, 2}
Green check.svg
keys param can be used to specify order.
70
_toArray({"c", "a", "b"})({
  a = "foo",
  c = true,
  b = 2,
})
{true, "foo", 2}
Green check.svg
keys param can be used to grab a subset of the keys.
71
_toArray({"a", "b"})({
  a = "foo",
  c = true,
  b = 2,
})
{"foo", 2}
Green check.svg
keys param can result in a sparse array if key not in tbl.
72
_toArray({"b", "a", "d", "c"})({
  a = "foo",
  c = true,
  b = 2,
})
{2, "foo", [4] = true}
Green check.svg
Sparse arrays can be padded with a custom padValue.
73
_toArray({"b", "a", "d", "c"}, "")({
  a = "foo",
  c = true,
  b = 2,
})
{2, "foo", "", true}
Green check.svg

Arrays

compact

compact(array)

Returns

  • Creates an array with falsey values removed.

Examples

#InputOutputResult
74
compact({0, false, 1, ""})
{0, 1, ""}
Green check.svg

concat

concat(array, ...)

Returns

  • Creates a new array concatenating array with any additional arrays and/or values.

Examples

#InputOutputResult
75
return utilsTable.concat({1}, 2, {3, 4}, {{5}}, {6})
{
  1,
  2,
  3,
  4,
  {5},
  6,
}
Green check.svg
Tables with only string keys are treated as single values.
76
concat({}, {1, 2}, {3, 4, foo = "bar"}, { foo = "quux" })
{
  1,
  2,
  3,
  4,
  { foo = "quux" },
}
Green check.svg

difference

difference(array, other)

Returns

  • An array of all the elements in array that are not in other.

Examples

#InputOutputResult
77
difference({"a", "b", "c"}, {"c", "d"})
{"a", "b"}
Green check.svg
Does not deep-compare.
78
difference(
  {
    { foo = "bar" },
  },
  {
    { foo = "bar" },
  }
)
{
  { foo = "bar" },
}
Green check.svg

dropWhile

dropWhile_dropWhile

dropWhile(array, predicate)

Returns

  • Creates a slice of array excluding elements dropped from the beginning. Elements are dropped until predicate returns falsey.

Examples

#InputOutputResult
79
local games = {"TLoZ", "TAoL", "ALttP", "LA", "OoT"}
return utilsTable.dropWhile(games, function(game)
  return game ~= "ALttP"
end)
{"ALttP", "LA", "OoT"}
Green check.svg
property shorthand
80
dropWhile(
  {
    {
      hasMasterSword = true,
      game = "SS",
    },
    {
      hasMasterSword = true,
      game = "ALBW",
    },
    {
      hasMasterSword = false,
      game = "TFH",
    },
    {
      hasMasterSword = true,
      game = "BotW",
    },
  },
  "hasMasterSword"
)
{
  {
    hasMasterSword = false,
    game = "TFH",
  },
  {
    hasMasterSword = true,
    game = "BotW",
  },
}
Green check.svg
81
local games = {"TLoZ", "TAoL", "ALttP", "LA", "OoT"}
return utilsTable.dropWhile(games, function(game)
  return game ~= "MM"
end)
{}
Green check.svg

_dropWhile(array)

Returns

  • Creates a slice of array excluding elements dropped from the beginning. Elements are dropped until predicate returns falsey.

Examples

#InputOutputResult
property shorthand
83
_dropWhile("hasMasterSword")({
  {
    hasMasterSword = true,
    game = "SS",
  },
  {
    hasMasterSword = true,
    game = "ALBW",
  },
  {
    hasMasterSword = false,
    game = "TFH",
  },
  {
    hasMasterSword = true,
    game = "BotW",
  },
})
{
  {
    hasMasterSword = false,
    game = "TFH",
  },
  {
    hasMasterSword = true,
    game = "BotW",
  },
}
Green check.svg

dropRightWhile

dropRightWhile_dropRightWhile

dropRightWhile(array, predicate)

Returns

  • Creates a slice of array excluding elements dropped from the end. Elements are dropped until predicate returns falsey.

Examples

#InputOutputResult
85
local games = {"...", "SS", "ALBW", "TFH", "BotW"}
return utilsTable.dropRightWhile(games, function(game)
  return game ~= "ALBW"
end)
{"...", "SS", "ALBW"}
Green check.svg
property shorthand
86
dropRightWhile(
  {
    {
      hasMasterSword = true,
      game = "SS",
    },
    {
      hasMasterSword = true,
      game = "ALBW",
    },
    {
      hasMasterSword = false,
      game = "TFH",
    },
    {
      hasMasterSword = true,
      game = "BotW",
    },
  },
  "hasMasterSword"
)
{
  {
    hasMasterSword = true,
    game = "SS",
  },
  {
    hasMasterSword = true,
    game = "ALBW",
  },
  {
    hasMasterSword = false,
    game = "TFH",
  },
}
Green check.svg
isMatch shorthand
87
dropRightWhile(
  {
    {
      system = "console",
      game = "SS",
    },
    {
      system = "handheld",
      game = "ALBW",
    },
    {
      system = "handheld",
      game = "TFH",
    },
    {
      system = "console",
      game = "BotW",
    },
  },
  { system = "console" }
)
{
  {
    system = "console",
    game = "SS",
  },
  {
    system = "handheld",
    game = "ALBW",
  },
  {
    system = "handheld",
    game = "TFH",
  },
}
Green check.svg

_dropRightWhile(array)

Returns

  • Creates a slice of array excluding elements dropped from the end. Elements are dropped until predicate returns falsey.

Examples

#InputOutputResult
property shorthand
89
_dropRightWhile("hasMasterSword")({
  {
    hasMasterSword = true,
    game = "SS",
  },
  {
    hasMasterSword = true,
    game = "ALBW",
  },
  {
    hasMasterSword = false,
    game = "TFH",
  },
  {
    hasMasterSword = true,
    game = "BotW",
  },
})
{
  {
    hasMasterSword = true,
    game = "SS",
  },
  {
    hasMasterSword = true,
    game = "ALBW",
  },
  {
    hasMasterSword = false,
    game = "TFH",
  },
}
Green check.svg
isMatch shorthand
90
_dropRightWhile({ system = "console" })({
  {
    game = "SS",
    system = "console",
  },
  {
    game = "ALBW",
    system = "handheld",
  },
  {
    game = "TFH",
    system = "handheld",
  },
  {
    game = "BotW",
    system = "console",
  },
})
{
  {
    game = "SS",
    system = "console",
  },
  {
    game = "ALBW",
    system = "handheld",
  },
  {
    game = "TFH",
    system = "handheld",
  },
}
Green check.svg

filter

filter_filter

filter(array, iteratee)

Returns

  • Iterates over array elements in array, returning an array of all elements iteratee returns truthy for.

Examples

#InputOutputResult
91
local args = {"foo", "", "bar"}
return utilsTable.filter(args, utilsString.notEmpty)
{"foo", "bar"}
Green check.svg
property shorthand
92
filter(
  {
    {
      canon = true,
      game = "The Wind Waker",
    },
    {
      canon = true,
      game = "Twilight Princess",
    },
    {
      canon = false,
      game = "Tingle's Rosy Rupeeland",
    },
  },
  "canon"
)
{
  {
    canon = true,
    game = "The Wind Waker",
  },
  {
    canon = true,
    game = "Twilight Princess",
  },
}
Green check.svg
isMatch shorthand
93
filter(
  {
    {
      type = "main",
      game = "The Wind Waker",
    },
    {
      type = "main",
      game = "Twilight Princess",
    },
    {
      type = "spinoff",
      game = "Tingle's Rosy Rupeeland",
    },
  },
  { type = "main" }
)
{
  {
    type = "main",
    game = "The Wind Waker",
  },
  {
    type = "main",
    game = "Twilight Princess",
  },
}
Green check.svg

_filter(array)

Returns

  • Iterates over array elements in array, returning an array of all elements iteratee returns truthy for.

Examples

#InputOutputResult
property shorthand
95
_filter("canon")({
  {
    canon = true,
    game = "The Wind Waker",
  },
  {
    canon = true,
    game = "Twilight Princess",
  },
  {
    canon = false,
    game = "Tingle's Rosy Rupeeland",
  },
})
{
  {
    canon = true,
    game = "The Wind Waker",
  },
  {
    canon = true,
    game = "Twilight Princess",
  },
}
Green check.svg
isMatch shorthand
96
_filter({ type = "main" })({
  {
    game = "The Wind Waker",
    type = "main",
  },
  {
    game = "Twilight Princess",
    type = "main",
  },
  {
    game = "Tingle's Rosy Rupeeland",
    type = "spinoff",
  },
})
{
  {
    game = "The Wind Waker",
    type = "main",
  },
  {
    game = "Twilight Princess",
    type = "main",
  },
}
Green check.svg

find

find_find

find(tbl, iteratee)

Returns

  • The value if found, else nil
  • The index of the value found, else nil

Examples

#InputOutputStatus
97
local args = {"foo", "bar", "baz"}
return utilsTable.find(args, utilsString._startsWith("b"))
"bar"
Green check.svg
2
Green check.svg
98
local args = {"foo", "quux", "quux"}
return utilsTable.find(args, utilsString._startsWith("b"))
nil
Green check.svg
nil
Green check.svg
property shorthand
99
find(
  {
    {
      canon = false,
      game = "Tingle's Rosy Rupeeland",
    },
    {
      canon = true,
      game = "The Wind Waker",
    },
    {
      canon = true,
      game = "Breath of the Wild",
    },
  },
  "canon"
)
{
  canon = true,
  game = "The Wind Waker",
}
Green check.svg
2
Green check.svg
isMatch shorthand
100
find(
  {
    {
      canon = false,
      game = "Tingle's Rosy Rupeeland",
      type = "spinoff",
    },
    {
      canon = true,
      game = "Twilight Princess HD",
      type = "remake",
    },
    {
      canon = true,
      game = "Breath of the Wild",
      type = "main",
    },
  },
  {
    canon = true,
    type = "main",
  }
)
{
  canon = true,
  game = "Breath of the Wild",
  type = "main",
}
Green check.svg
3
Green check.svg

_find(tbl)

Returns

  • The value if found, else nil
  • The index of the value found, else nil

Examples

#InputOutputStatus
property shorthand
103
_find("canon")({
  {
    canon = false,
    game = "Tingle's Rosy Rupeeland",
  },
  {
    canon = true,
    game = "The Wind Waker",
  },
  {
    canon = true,
    game = "Breath of the Wild",
  },
})
{
  canon = true,
  game = "The Wind Waker",
}
Green check.svg
2
Green check.svg
isMatch shorthand
104
_find({
  canon = true,
  type = "main",
})({
  {
    canon = false,
    game = "Tingle's Rosy Rupeeland",
    type = "spinoff",
  },
  {
    canon = true,
    game = "Twilight Princess HD",
    type = "remake",
  },
  {
    canon = true,
    game = "Breath of the Wild",
    type = "main",
  },
})
{
  canon = true,
  game = "Breath of the Wild",
  type = "main",
}
Green check.svg
3
Green check.svg

findIndex

findIndex(tbl, iteratee)

Returns

  • The index of the value if found, else nil

Examples

#InputOutputStatus
105
local args = {"foo", "bar", "baz"}
return utilsTable.findIndex(args, utilsString._startsWith("b"))
2
Green check.svg
106
local args = {"foo", "quux", "quux"}
return utilsTable.findIndex(args, utilsString._startsWith("b"))
nil
Green check.svg
property shorthand
107
findIndex(
  {
    {
      canon = false,
      game = "Tingle's Rosy Rupeeland",
    },
    {
      canon = true,
      game = "The Wind Waker",
    },
    {
      canon = true,
      game = "Breath of the Wild",
    },
  },
  "canon"
)
2
Green check.svg
isMatch shorthand
108
findIndex(
  {
    {
      canon = false,
      game = "Tingle's Rosy Rupeeland",
      type = "spinoff",
    },
    {
      canon = true,
      game = "Twilight Princess HD",
      type = "remake",
    },
    {
      canon = true,
      game = "Breath of the Wild",
      type = "main",
    },
  },
  {
    canon = true,
    type = "main",
  }
)
3
Green check.svg

findLast

findLast_findLast

findLast(array, iteratee)

Returns

  • The last value found matching iteratee, else nil.
  • The index of the value, else nil.

Examples

#InputOutputStatus
109
local args = {"foo", "bar", "baz"}
return utilsTable.findLast(args, utilsString._startsWith("b"))
"baz"
Green check.svg
3
Green check.svg
110
local args = {"foo", "quux", "quux"}
return utilsTable.findLast(args, utilsString._startsWith("b"))
nil
Green check.svg
nil
Green check.svg
property shorthand
111
findLast(
  {
    {
      canon = false,
      game = "Tingle's Rosy Rupeeland",
    },
    {
      canon = true,
      game = "The Wind Waker",
    },
    {
      canon = true,
      game = "Breath of the Wild",
    },
  },
  "canon"
)
{
  canon = true,
  game = "Breath of the Wild",
}
Green check.svg
3
Green check.svg
isMatch shorthand
112
findLast(
  {
    {
      canon = false,
      game = "Tingle's Rosy Rupeeland",
      type = "spinoff",
    },
    {
      canon = true,
      game = "Twilight Princess",
      type = "main",
    },
    {
      canon = true,
      game = "Breath of the Wild",
      type = "main",
    },
  },
  {
    canon = true,
    type = "main",
  }
)
{
  canon = true,
  game = "Breath of the Wild",
  type = "main",
}
Green check.svg
3
Green check.svg

_findLast(array)

Returns

  • The last value found matching iteratee, else nil.
  • The index of the value, else nil.

Examples

#InputOutputStatus
property shorthand
115
_findLast("canon")({
  {
    canon = false,
    game = "Tingle's Rosy Rupeeland",
  },
  {
    canon = true,
    game = "The Wind Waker",
  },
  {
    canon = true,
    game = "Breath of the Wild",
  },
})
{
  canon = true,
  game = "Breath of the Wild",
}
Green check.svg
3
Green check.svg
isMatch shorthand
116
_findLast({
  canon = true,
  type = "main",
})({
  {
    canon = false,
    game = "Tingle's Rosy Rupeeland",
    type = "spinoff",
  },
  {
    canon = true,
    game = "Twilight Princess",
    type = "main",
  },
  {
    canon = true,
    game = "Breath of the Wild",
    type = "main",
  },
})
{
  canon = true,
  game = "Breath of the Wild",
  type = "main",
}
Green check.svg
3
Green check.svg

flatten

flatten(array)

Returns

  • Returns array but flattened a single level deep.

Examples

#InputOutputResult
117
flatten({
  1,
  {
    2,
    {3, 4},
  },
  5,
})
{
  1,
  2,
  {3, 4},
  5,
}
Green check.svg

flatMap

flatMap_flatMap

flatMap(array, iteratee)

Returns

  • A flattened array of values created by running each element in array thru iteratee and flattening the mapped results.

Examples

#InputOutputResult
118
local function duplicate(n)
  return {n, n}
end
return utilsTable.flatMap({1, 2}, duplicate)
{1, 1, 2, 2}
Green check.svg

_flatMap(array)

Returns

  • A flattened array of values created by running each element in array thru iteratee and flattening the mapped results.

Examples

#InputOutputResult
119
local duplicate = utilsTable._flatMap(function(n)
  return {n, n}
end)
return duplicate({1, 2})
{1, 1, 2, 2}
Green check.svg

fromPairs

fromPairs(pairs)

Returns

  • An object composed from key-value pairs.

Examples

#InputOutputResult
120
fromPairs({
  {"a", 1},
  {"b", 2},
})
{
  a = 1,
  b = 2,
}
Green check.svg

groupBy

groupBy_groupBy

groupBy(array, iteratee)

Returns

  • A table composed of keys generated from the results of running each element of array thru iteratee. The order of grouped values is determined by the order they occur in array. The corresponding value of each key is an array of elements responsible for generating the key. If a nil key is generated for a given value, that value will be absent from the resulting table.

Examples

#InputOutputResult
121
return utilsTable.groupBy({6.1, 4.2, 6.3}, math.floor)
{
  [6] = {6.1, 6.3},
  [4] = {4.2},
}
Green check.svg
property shorthand
122
groupBy(
  {
    {
      term = "Hero of Time",
      game = "OoT",
      page = "Link",
    },
    {
      term = "Hero of Winds",
      game = "TWW",
      page = "Link",
    },
    {
      term = "Zelda",
      game = "SS",
      page = "Princess Zelda",
    },
    { someOtherData = "foo" },
  },
  "page"
)
{
  ["Princess Zelda"] = {
    {
      term = "Zelda",
      game = "SS",
      page = "Princess Zelda",
    },
  },
  Link = {
    {
      term = "Hero of Time",
      game = "OoT",
      page = "Link",
    },
    {
      term = "Hero of Winds",
      game = "TWW",
      page = "Link",
    },
  },
}
Green check.svg

_groupBy(array)

Returns

  • A table composed of keys generated from the results of running each element of array thru iteratee. The order of grouped values is determined by the order they occur in array. The corresponding value of each key is an array of elements responsible for generating the key. If a nil key is generated for a given value, that value will be absent from the resulting table.

Examples

#InputOutputResult
property shorthand
124
_groupBy("page")({
  {
    term = "Hero of Time",
    game = "OoT",
    page = "Link",
  },
  {
    term = "Hero of Winds",
    game = "TWW",
    page = "Link",
  },
  {
    term = "Zelda",
    game = "SS",
    page = "Princess Zelda",
  },
  { someOtherData = "foo" },
})
{
  ["Princess Zelda"] = {
    {
      term = "Zelda",
      game = "SS",
      page = "Princess Zelda",
    },
  },
  Link = {
    {
      term = "Hero of Time",
      game = "OoT",
      page = "Link",
    },
    {
      term = "Hero of Winds",
      game = "TWW",
      page = "Link",
    },
  },
}
Green check.svg

includes

includes(array, value)

Returns

  • True if and only if value is in array.

Examples

#InputOutputResult
125
includes({"foo", "bar"}, "foo")
true
Green check.svg
126
includes({"foo", "bar"}, "baz")
false
Green check.svg

intersection

intersection(array, other)

Returns

  • An array of all the elements that are in both array and other

Examples

#InputOutputResult
127
intersection({"a", "b", "c"}, {"b"})
{"b"}
Green check.svg
Does not deep-compare.
128
intersection(
  {
    { foo = "bar" },
  },
  {
    { foo = "bar" },
  }
)
{}
Green check.svg

keyBy

keyBy_keyBy

keyBy(array, iteratee)

Returns

  • Creates a table composed of keys generated from the results of running each element of array thru iteratee

Examples

#InputOutputResult
129
local characters = {
  {
    name = "Link",
    game = "TWW",
    age = 10,
  },
  {
    name = "Link",
    game = "TP",
    age = 17
  },
}
return utilsTable.keyBy(characters, function(character)
  return character.game .. " " .. character.name
end)
{
  ["TP Link"] = {
    game = "TP",
    name = "Link",
    age = 17,
  },
  ["TWW Link"] = {
    game = "TWW",
    name = "Link",
    age = 10,
  },
}
Green check.svg
property shorthand
130
keyBy(
  {
    {
      name = "Link",
      age = 10,
    },
    {
      name = "Zelda",
      age = 10,
    },
    {
      name = "Zelda",
      age = 17,
    },
  },
  "name"
)
{
  Zelda = {
    name = "Zelda",
    age = 17,
  },
  Link = {
    name = "Link",
    age = 10,
  },
}
Green check.svg

_keyBy(array)

Returns

  • Creates a table composed of keys generated from the results of running each element of array thru iteratee

Examples

#InputOutputResult
property shorthand
132
_keyBy("name")({
  {
    name = "Link",
    age = 10,
  },
  {
    name = "Zelda",
    age = 10,
  },
  {
    name = "Zelda",
    age = 17,
  },
})
{
  Zelda = {
    name = "Zelda",
    age = 17,
  },
  Link = {
    name = "Link",
    age = 10,
  },
}
Green check.svg

len

len(array)

Returns

Examples

#InputOutputResult
133
len({1, 2, 3, [10] = 10})
3
Green check.svg

map

map_map

map(array, iteratee)

Returns

  • Creates an array of values by running each array element in array thru iteratee.

Examples

#InputOutputResult
134
local args = {true, false}
return utilsTable.map(args, tostring)
{"true", "false"}
Green check.svg
property shorthand
135
map(
  {
    {
      name = "Link",
      triforce = "Courage",
    },
    {
      name = "Zelda",
      triforce = "Wisdom",
    },
    {
      name = "Ganon",
      triforce = "Power",
    },
  },
  "triforce"
)
{"Courage", "Wisdom", "Power"}
Green check.svg

_map(array)

Returns

  • Creates an array of values by running each array element in array thru iteratee.

Examples

#InputOutputResult
property shorthand
137
_map("triforce")({
  {
    name = "Link",
    triforce = "Courage",
  },
  {
    name = "Zelda",
    triforce = "Wisdom",
  },
  {
    name = "Ganon",
    triforce = "Power",
  },
})
{"Courage", "Wisdom", "Power"}
Green check.svg

min

min(array)

Returns

  • The maximum value of array, or nil if empty.

Examples

#InputOutputResult
138
min({3, 2, 1})
1
Green check.svg
139
min({})
nil
Green check.svg

max

max(array)

Returns

  • The maximum value of array, or nil if empty.

Examples

#InputOutputResult
140
max({5, 10, 20})
20
Green check.svg
141
max({})
nil
Green check.svg

padNils

padNils_padNils

padNils(array, [padValue], [max])

Parameters

Returns

  • Returns a version of array such that nil-valued indices up to and including max are replaced with padValue.

Examples

#InputOutputResult
142
padNils({[2] = 2, [4] = 4 }, 0)
{0, 2, 0, 4}
Green check.svg
143
padNils({[2] = 2, [4] = 4 }, 0, 1)
{0, 2, [4] = 4}
Green check.svg
144
padNils({[2] = 2, [4] = 4 }, 0, 6)
{0, 2, 0, 4, 0, 0}
Green check.svg
145
padNils({"foo", [3] = "baz"})
{"foo", "", "baz"}
Green check.svg

_padNils(array)

Parameters

Returns

  • Returns a version of array such that nil-valued indices up to and including max are replaced with padValue.

Examples

#InputOutputResult
146
_padNils(0)({
  [2] = 2,
  [4] = 4,
})
{0, 2, 0, 4}
Green check.svg
147
_padNils(0, 1)({
  [2] = 2,
  [4] = 4,
})
{0, 2, [4] = 4}
Green check.svg
148
_padNils(0, 6)({
  [2] = 2,
  [4] = 4,
})
{0, 2, 0, 4, 0, 0}
Green check.svg
149
_padNils()({"foo", [3] = "baz"})
{"foo", "", "baz"}
Green check.svg

partition

partition_partition

partition(array, iteratee)

Returns

  • array elements that iteratee returns truthy for.
  • array elements that iteratee returns falsey for.

Examples

#InputOutputStatus
150
local tbl = {"foo", "bar", "baz", "quux"}
return utilsTable.partition(tbl, function(str)
  return str:sub(1, 1) ~= "b"
end)
{"foo", "quux"}
Green check.svg
{"bar", "baz"}
Green check.svg
property shorthand
151
partition(
  {
    {
      canon = true,
      game = "The Wind Waker",
    },
    {
      canon = true,
      game = "Twilight Princess",
    },
    {
      canon = false,
      game = "Tingle's Rosy Rupeeland",
    },
  },
  "canon"
)
{
  {
    canon = true,
    game = "The Wind Waker",
  },
  {
    canon = true,
    game = "Twilight Princess",
  },
}
Green check.svg
{
  {
    canon = false,
    game = "Tingle's Rosy Rupeeland",
  },
}
Green check.svg
isMatch shorthand
152
partition(
  {
    {
      type = "main",
      game = "The Wind Waker",
    },
    {
      type = "main",
      game = "Twilight Princess",
    },
    {
      type = "spinoff",
      game = "Tingle's Rosy Rupeeland",
    },
  },
  { type = "main" }
)
{
  {
    type = "main",
    game = "The Wind Waker",
  },
  {
    type = "main",
    game = "Twilight Princess",
  },
}
Green check.svg
{
  {
    type = "spinoff",
    game = "Tingle's Rosy Rupeeland",
  },
}
Green check.svg

_partition(array)

Returns

  • array elements that iteratee returns truthy for.
  • array elements that iteratee returns falsey for.

Examples

#InputOutputStatus
property shorthand
154
_partition("canon")({
  {
    canon = true,
    game = "The Wind Waker",
  },
  {
    canon = true,
    game = "Twilight Princess",
  },
  {
    canon = false,
    game = "Tingle's Rosy Rupeeland",
  },
})
{
  {
    canon = true,
    game = "The Wind Waker",
  },
  {
    canon = true,
    game = "Twilight Princess",
  },
}
Green check.svg
{
  {
    canon = false,
    game = "Tingle's Rosy Rupeeland",
  },
}
Green check.svg
isMatch shorthand
155
_partition({ type = "main" })({
  {
    game = "The Wind Waker",
    type = "main",
  },
  {
    game = "Twilight Princess",
    type = "main",
  },
  {
    game = "Tingle's Rosy Rupeeland",
    type = "spinoff",
  },
})
{
  {
    game = "The Wind Waker",
    type = "main",
  },
  {
    game = "Twilight Princess",
    type = "main",
  },
}
Green check.svg
{
  {
    game = "Tingle's Rosy Rupeeland",
    type = "spinoff",
  },
}
Green check.svg

reverse

reverse(array)

Returns

  • Reverses array so that the first element becomes the last, the second element becomes the second to last, and so on.

Examples

#InputOutputResult
156
reverse({1, 2, 3})
{3, 2, 1}
Green check.svg
Ignores non-consecutive integer keys
157
reverse({1, 2, 3, [100] = 100})
{3, 2, 1}
Green check.svg

slice

slice_slice

slice(array, start, [end])

Parameters

Returns

  • Creates a slice of array from start up to and including end.

Examples

#InputOutputResult
158
slice({"a", "b", "c"}, 1, 2)
{"a", "b"}
Green check.svg
159
slice({"a", "b", "c"}, 2)
{"b", "c"}
Green check.svg

_slice(array)

Parameters

Returns

  • Creates a slice of array from start up to and including end.

Examples

#InputOutputResult
160
_slice(1, 2)({"a", "b", "c"})
{"a", "b"}
Green check.svg
161
_slice(2)({"a", "b", "c"})
{"b", "c"}
Green check.svg

sortBy

sortBy_sortBy

sortBy(array, iteratees)

Returns

  • An array of elements, sorted in ascending order by the results of running each element in array thru each iteratee. This method performs an unstable sort, that is, it does not guarantee that the original order of equal elements will be preserved.

Examples

#InputOutputResult
162
local games = {
  {
    game = "LA",
    systems = {"GB", "GBC", "3DS VC"}
  },
  {
    game = "OoT",
    systems = {"N64", "GCN", "iQue", "Wii VC", "Wii U VC"},
  },
  {
    game = "TWW",
    systems = {"GCN", "Wii U"},
  },
}
return utilsTable.sortBy(games, function(game)
  return #game.systems
end)
{
  {
    game = "TWW",
    systems = {"GCN", "Wii U"},
  },
  {
    game = "LA",
    systems = {"GB", "GBC", "3DS VC"},
  },
  {
    game = "OoT",
    systems = {"N64", "GCN", "iQue", "Wii VC", "Wii U VC"},
  },
}
Green check.svg
property shorthand
163
sortBy(
  {
    {
      name = "Link",
      age = 10,
    },
    {
      name = "Zelda",
      age = 10,
    },
    {
      name = "Zelda",
      age = 17,
    },
    {
      name = "Link",
      age = 17,
    },
  },
  "name"
)
{
  {
    name = "Link",
    age = 10,
  },
  {
    name = "Link",
    age = 17,
  },
  {
    name = "Zelda",
    age = 17,
  },
  {
    name = "Zelda",
    age = 10,
  },
}
Green check.svg
Multiple sort criteria
164
sortBy(
  {
    {
      name = "Link",
      age = 10,
    },
    {
      name = "Zelda",
      age = 10,
    },
    {
      name = "Zelda",
      age = 17,
    },
    {
      name = "Link",
      age = 17,
    },
  },
  {"name", "age"}
)
{
  {
    name = "Link",
    age = 10,
  },
  {
    name = "Link",
    age = 17,
  },
  {
    name = "Zelda",
    age = 10,
  },
  {
    name = "Zelda",
    age = 17,
  },
}
Green check.svg

_sortBy(array)

Returns

  • An array of elements, sorted in ascending order by the results of running each element in array thru each iteratee. This method performs an unstable sort, that is, it does not guarantee that the original order of equal elements will be preserved.

Examples

#InputOutputResult
property shorthand
166
_sortBy("name")({
  {
    name = "Link",
    age = 10,
  },
  {
    name = "Zelda",
    age = 10,
  },
  {
    name = "Zelda",
    age = 17,
  },
  {
    name = "Link",
    age = 17,
  },
})
{
  {
    name = "Link",
    age = 10,
  },
  {
    name = "Link",
    age = 17,
  },
  {
    name = "Zelda",
    age = 17,
  },
  {
    name = "Zelda",
    age = 10,
  },
}
Green check.svg
Multiple sort criteria
167
_sortBy({"name", "age"})({
  {
    name = "Link",
    age = 10,
  },
  {
    name = "Zelda",
    age = 10,
  },
  {
    name = "Zelda",
    age = 17,
  },
  {
    name = "Link",
    age = 17,
  },
})
{
  {
    name = "Link",
    age = 10,
  },
  {
    name = "Link",
    age = 17,
  },
  {
    name = "Zelda",
    age = 10,
  },
  {
    name = "Zelda",
    age = 17,
  },
}
Green check.svg

tail

tail(array)

Returns

  • Gets all but the first element of array.

Examples

#InputOutputResult
168
tail({1, 2, 3})
{2, 3}
Green check.svg
169
tail({})
{}
Green check.svg

take

take_take

take(array, n)

Returns

  • Creates a slice of array with n elements taken from the beginning.

Examples

#InputOutputResult
170
take({1, 2, 3}, 2)
{1, 2}
Green check.svg
171
take({1, 2, 3}, 5)
{1, 2, 3}
Green check.svg
172
take({1, 2, 3}, 0)
{}
Green check.svg

_take(array)

Returns

  • Creates a slice of array with n elements taken from the beginning.

Examples

#InputOutputResult
173
_take(2)({1, 2, 3})
{1, 2}
Green check.svg
174
_take(5)({1, 2, 3})
{1, 2, 3}
Green check.svg
175
_take(0)({1, 2, 3})
{}
Green check.svg

takeWhile

takeWhile_takeWhile

takeWhile(array, predicate)

Returns

  • Creates a slice of array with elements taken from the beginning. Elements are taken until predicate returns falsey.

Examples

#InputOutputResult
176
local games = {"TLoZ", "TAoL", "ALttP", "LA", "OoT", "MM"}
local gamesBeforeOoT = utilsTable.takeWhile(games, function(game) 
  return game ~= "OoT"
end)
return gamesBeforeOoT
{"TLoZ", "TAoL", "ALttP", "LA"}
Green check.svg
property shorthand
177
takeWhile(
  {
    {
      is2D = true,
      game = "TLoZ",
    },
    {
      is2D = true,
      game = "TAoL",
    },
    {
      is2D = true,
      game = "ALttP",
    },
    {
      is2D = true,
      game = "LA",
    },
    {
      is2D = false,
      game = "OoT",
    },
    {
      is2D = true,
      game = "TMC",
    },
  },
  "is2D"
)
{
  {
    is2D = true,
    game = "TLoZ",
  },
  {
    is2D = true,
    game = "TAoL",
  },
  {
    is2D = true,
    game = "ALttP",
  },
  {
    is2D = true,
    game = "LA",
  },
}
Green check.svg
isMatch shorthand
178
takeWhile(
  {
    {
      system = "console",
      game = "TLoZ",
    },
    {
      system = "console",
      game = "TAoL",
    },
    {
      system = "console",
      game = "ALttP",
    },
    {
      system = "handheld",
      game = "LA",
    },
    {
      system = "console",
      game = "OoT",
    },
  },
  { system = "console" }
)
{
  {
    system = "console",
    game = "TLoZ",
  },
  {
    system = "console",
    game = "TAoL",
  },
  {
    system = "console",
    game = "ALttP",
  },
}
Green check.svg

_takeWhile(array)

Returns

  • Creates a slice of array with elements taken from the beginning. Elements are taken until predicate returns falsey.

Examples

#InputOutputResult
property shorthand
180
_takeWhile("is2D")({
  {
    game = "TLoZ",
    is2D = true,
  },
  {
    game = "TAoL",
    is2D = true,
  },
  {
    game = "ALttP",
    is2D = true,
  },
  {
    game = "LA",
    is2D = true,
  },
  {
    game = "OoT",
    is2D = false,
  },
  {
    game = "TMC",
    is2D = true,
  },
})
{
  {
    game = "TLoZ",
    is2D = true,
  },
  {
    game = "TAoL",
    is2D = true,
  },
  {
    game = "ALttP",
    is2D = true,
  },
  {
    game = "LA",
    is2D = true,
  },
}
Green check.svg
isMatch shorthand
181
_takeWhile({ system = "console" })({
  {
    game = "TLoZ",
    system = "console",
  },
  {
    game = "TAoL",
    system = "console",
  },
  {
    game = "ALttP",
    system = "console",
  },
  {
    game = "LA",
    system = "handheld",
  },
  {
    game = "OoT",
    system = "console",
  },
})
{
  {
    game = "TLoZ",
    system = "console",
  },
  {
    game = "TAoL",
    system = "console",
  },
  {
    game = "ALttP",
    system = "console",
  },
}
Green check.svg

union

union(arrays)

Parameters

Returns

  • An array of unique values, in order, from all given arrays.

Examples

#InputOutputResult
182
union({
  {"a", "b", "c"},
  {"b"},
  {"c", "d"},
})
{"a", "b", "c", "d"}
Green check.svg
Does not deep-compare for equality.
183
union({
  {
    { foo = "bar" },
    { foo = "bar" },
  },
})
{
  { foo = "bar" },
  { foo = "bar" },
}
Green check.svg

unique

unique(array)

Returns

  • A copy of array but without the duplicate values. Elements are deep-compared. he order of result values is determined by the order they occur in the array.

Examples

#InputOutputResult
184
unique({
  1,
  2,
  2,
  { foo = "bar" },
  { foo = "quux" },
  { foo = "bar" },
})
{
  1,
  2,
  { foo = "bar" },
  { foo = "quux" },
}
Green check.svg

uniqueBy

uniqueBy_uniqueBy

uniqueBy(array, iteratee)

Returns

  • A copy of array but without the duplicate values. iteratee is invoked for each element in array to generate the criterion by which uniqueness is computed.

Examples

#InputOutputResult
185
local games = {
  { title = "LA", game = "LA" },
  { title = "OoT", game = "OoT" },
  { title = "LADX", game = "LA" },
  { title = "OoT3D", game = "OoT" },
  { title = "LANS", game = "LA" },
}
return utilsTable.uniqueBy(games, function(game) return game.game end)
{
  {
    title = "LA",
    game = "LA",
  },
  {
    title = "OoT",
    game = "OoT",
  },
}
Green check.svg
property shorthand
186
uniqueBy(
  {
    {
      title = "LA",
      game = "LA",
    },
    {
      title = "OoT",
      game = "OoT",
    },
    {
      title = "LADX",
      game = "LA",
    },
    {
      title = "OoT3D",
      game = "OoT",
    },
    {
      title = "LANS",
      game = "LA",
    },
  },
  "game"
)
{
  {
    title = "LA",
    game = "LA",
  },
  {
    title = "OoT",
    game = "OoT",
  },
}
Green check.svg

_uniqueBy(array)

Returns

  • A copy of array but without the duplicate values. iteratee is invoked for each element in array to generate the criterion by which uniqueness is computed.

Examples

#InputOutputResult
property shorthand
188
_uniqueBy("game")({
  {
    title = "LA",
    game = "LA",
  },
  {
    title = "OoT",
    game = "OoT",
  },
  {
    title = "LADX",
    game = "LA",
  },
  {
    title = "OoT3D",
    game = "OoT",
  },
  {
    title = "LANS",
    game = "LA",
  },
})
{
  {
    title = "LA",
    game = "LA",
  },
  {
    title = "OoT",
    game = "OoT",
  },
}
Green check.svg

zip

zip(arrays, [padValue])

Parameters

Returns

  • Creates a transposition of arrays. That is, an array of grouped elements, the first of which contains the first elements of the given arrays, the second of which contains the second elements of the given arrays, and so on. Should the elements of arrays not be of the same length, the resulting groups can be padded to the same length with padValue.

Examples

#InputOutputResult
189
zip({
  {1, 2},
  {"a", "b"},
  {true, false},
})
{
  {1, "a", true},
  {2, "b", false},
}
Green check.svg
190
zip(
  {
    {1, 2},
    {"a", "b", "c"},
    {true},
  },
  ""
)
{
  {1, "a", true},
  {2, "b", ""},
  {"", "c", ""},
}
Green check.svg
191
zip({
  {1, 2},
  {"a", "b", "c"},
  {true},
})
{
  {1, "a", true},
  {2, "b"},
  { [2] = "c" },
}
Green check.svg

local p = {}
local h = {}

-- HELPERS

function h.append(tbl, val)
	tbl[table.maxn(tbl)+1] = val
end

function h.mapper(iteratee)
	if type(iteratee) == "function" then
		return iteratee
	end
	if type(iteratee) == "string" or type(iteratee) == "number" then
		return p._property(iteratee) 
	end
end

function h.predicate(iteratee)
	if type(iteratee) == "function" then
		return iteratee
	end
	if type(iteratee) == "string" or type(iteratee) == "number" then
		return p._property(iteratee)
	end
	if type(iteratee) == "table" then
		return p._isMatch(iteratee)
	end
	return iteratee
end

-- GENERAL

function p.clone(val)
	if type(val) ~= "table" then
		return val
	end
	local result = {}
	for k, v in pairs(val) do
		result[k] = v
	end
	return result
end

function p.cloneDeep(val)
	if type(val) ~= "table" then
		return val
	end
	return p.merge({}, val)
end

function p.hasArray(tbl)
	if type(tbl) ~= "table" then
		return false
	end
	return p.size(tbl) == 0 or p.len(tbl) > 0
end

function p.hasKey(tbl, key)
	return p._hasKey(key)(tbl)
end
function p._hasKey(key)
	return function(tbl)
		return not not tbl[key]
	end
end

function p.invert(tbl)
	local inverted = {}
	for k, v in pairs(tbl) do
		inverted[v] = k
	end
	return inverted
end

function p.isArray(tbl)
	if type(tbl) ~= "table" then
		return false
	end
	for k, v in pairs(tbl) do
		if type(k) ~= "number" then
			return false
		end
	end
	return true
end

function p.isEmpty(tbl)
	return p.size(tbl) == 0
end

function p.isEqual(tbl, other)
	return p._isEqual(tbl)(other)
end
function p._isEqual(tbl)
	return function(other)
		if type(tbl) ~= "table" or type(other) ~= "table" then
			return tbl == other
		end
		return p.isMatch(other, tbl) and p.isMatch(tbl, other)
	end
end

function p.isMatch(tbl, source)
	return p._isMatch(source)(tbl)
end
function p._isMatch(sourceTbl)
	return function(tbl)
		if sourceTbl == tbl then
			return true
		end
		if type(sourceTbl) ~= type(tbl) then
			return false
		end
		if p.size(sourceTbl) == 0 and p.size(tbl) > 0 then
			return false
		end
		for k, v in pairs(sourceTbl) do
			if type(v) ~= "table" and v ~= tbl[k] then
				return false
			end
			if type(v) == "table" and not p.isMatch(tbl[k], v) then
				return false
			end
		end
		return true
	end
end

function p.ivalues(tbl)
	local result = {}
	for _, v in ipairs(tbl) do
		table.insert(result, v)
	end
	return result
end

function p.keyOf(tbl, val)
	for k, v in pairs(tbl) do
		if v == val then
			return k
		end
	end
	return nil
end

function p.keys(tbl)
   local result = {}
   for k in pairs(tbl) do
   		h.append(result, k)
   end
   return result
end

function p.mapValues(tbl, iteratee)
	return p._mapValues(iteratee)(tbl)
end
function p._mapValues(iteratee)
	local mappingFunction = h.mapper(iteratee)
	return function(tbl)
		local result = {}
		for k, v in pairs(tbl) do
			result[k] = mappingFunction(v)
		end
		return result
	end
end

function p.merge(tbl, ...)
	if tbl == nil then
		return nil
	end
	for _, source in ipairs({...}) do
		for k, v in pairs(source) do
			if type(v) == "table" and type(tbl[k]) == "table" then
				tbl[k] = p.merge({}, tbl[k], v)
			else
				tbl[k] = p.clone(v)
			end
		end
	end
	return tbl
end

local inspect
local MAX_SINGLELINE = 50 -- If changing this, also change the variable of the same name at [[Module:UtilsTable/Documentation/Data]] 
function p.print(tbl, singleLine)
	inspect = inspect or require("Module:UtilsTable/Inspect") -- lazy-loaded for performance optimization
	return inspect(tbl, {
		multiline = function(t)
			if singleLine then
				return false
			end
			local size = 0
			for key, val in pairs(t) do
				if type(val) == "table" then
					return true
				end
				size = size + 1
			end
			local singleLineLength = #inspect(t, { multiline = false })
			return singleLineLength > MAX_SINGLELINE or size > #t and size - #t > 1
		end
	})
end

function p.printPath(pathComponents)
	local path = ""
	for _, pathComponent in pairs(pathComponents or {}) do
		if string.match(pathComponent, "^[A-Za-z_][A-Za-z_0-9]*$") then
			path = path .. "." .. pathComponent
		elseif string.match(pathComponent, "^%[.*%]$") then
			path = path .. pathComponent
		else
			path = path .. "[" .. p.print(pathComponent) .. "]"
		end
	end
	return path
end

function p.property(tbl, path)
	return p._property(path)(tbl)
end
function p._property(path)
	return function(tbl)
		if type(path) ~= "table" then
			path = { path }
		end
		local result = tbl
		for i, key in ipairs(path) do
			result = result[key] or result[mw.text.trim(key, '%[%]"')]
			if result == nil then
				return result
			end
		end
		return result
	end
end

function p.size(tbl)
	return #p.keys(tbl)
end

function p.stringKeys(tbl)
	local result = {}
	for k in pairs(tbl) do
		if type(k) == "string" then
			table.insert(result, k)
		end
	end
	return result
end

function p.toArray(tbl, keys, padValue)
	return p._toArray(keys, padValue)(tbl)
end
function p._toArray(keys, padValue)
	return function(tbl)
		local array = {}
		if keys then
			for i, key in ipairs(keys) do
				array[i] = tbl[key] or padValue
			end
		else
			for k, v in pairs(tbl) do
				table.insert(array, v)
			end
		end
		return array
	end
end

--[[
	"Array" functions (using the `ipairs` iterator, mostly)
--]]

function p.compact(array)
	local result = {}
	local j = 1
	for i = 1, table.maxn(array) do
		if array[i] then
			result[j] = array[i]
			j = j + 1
		end
	end
	return result
end

function p.concat(array, ...)
	if type(array) ~= "table" then
		array = {array}
	end
	local result = p.clone(array)
	for i, arrayOrValue in ipairs({...}) do
		if not p.hasArray(arrayOrValue) then
			h.append(result, arrayOrValue)
		else
			for _, value in ipairs(arrayOrValue) do
				h.append(result, value)
			end
		end
	end
	return result
end

function p.difference(array, other)
	local result = {}
	local lookup = p.invert(other)
	for i, v in ipairs(array) do
		if not lookup[v] then
			table.insert(result, v)
		end
	end
	return result
end

function p.dropWhile(array, predicate)
	return p._dropWhile(predicate)(array) 
end
function p._dropWhile(predicate)
	local predicate = h.predicate(predicate)
	return function(array)
		local i = 1
		while i <= #array and predicate(array[i], i) do
			i = i + 1
		end
		return p.slice(array, i)
	end
end

function p.dropRightWhile(array, predicate)
	return p._dropRightWhile(predicate)(array)
end
function p._dropRightWhile(predicate)
	local predicate = h.predicate(predicate)
	return function(array)
		local result = {}
		local i = p.len(array)
		while i > 0 and predicate(array[i], i) do
			i = i - 1
		end
		while i > 0 do
			table.insert(result, 1, array[i])
			i = i - 1
		end
		return result
	end
end

function p.filter(array, iteratee)
	return p._filter(iteratee)(array)
end
function p._filter(iteratee)
	return function(array)
		local predicateFn = h.predicate(iteratee)
		local results = {}
		for i, v in ipairs(array) do
			if predicateFn(v) then
				table.insert(results, v)
			end
		end
		return results
	end
end

function p.find(array, iteratee)
	return p._find(iteratee)(array)
end
function p._find(iteratee)
	local predicate = h.predicate(iteratee)
	return function(array)
		for i, v in ipairs(array) do
			if predicate(v) then
				return v, i
			end
		end
		return nil, nil
	end
end

function p.findIndex(array, iteratee)
	local index = select(2, p.find(array, iteratee))
	return index
end

function p.findLast(array, iteratee)
	return p._findLast(iteratee)(array)
end
function p._findLast(iteratee)
	local predicate = h.predicate(iteratee)
	return function(array)
		local v, i = p.find(p.reverse(array), predicate)
		if not i then
			return nil, nil
		end
		return v, p.len(array) - i + 1
	end
end

function p.flatten(array)
	local result = {}
	for _, v in ipairs(array) do
		result = p.concat(result, v)
	end
	return result
end

function p.flatMap(array, mappingFunction)
	return p._flatMap(mappingFunction)(array)
end
function p._flatMap(mappingFunction)
	return function(array)
		return p.flatten(p.map(array, mappingFunction))
	end
end

function p.fromPairs(pairs)
	local result = {}
	for i, pair in ipairs(pairs) do
		result[pair[1]] = pair[2]
	end
	return result
end

function p.groupBy(array, iteratee)
	return p._groupBy(iteratee)(array)
end
function p._groupBy(iteratee)
	local mappingFn = h.mapper(iteratee)
	return function(array)
		local result = {}
		for _, v in ipairs(array) do
			local groupingKey = mappingFn(v)
			if groupingKey then
				local group = result[groupingKey] or {}
				result[groupingKey] = p.concat(group, v)
			end
		end
		return result
	end
end

function p.includes(array, value)
	for _, v in ipairs(array) do
		if v == value then
			return true
		end
	end
	return false
end

function p.intersection(array, other)
	local result = {}
	for i, v in ipairs(array) do
		if p.keyOf(other, v) then
			table.insert(result, v)
		end
	end
	return result
end

function p.keyBy(array, iteratee)
	return p._keyBy(iteratee)(array)
end
function p._keyBy(iteratee)
	local mapper = h.mapper(iteratee)
	return function(array)
		local result = {}
		for i, v in ipairs(array) do
			result[mapper(v)] = v
		end
		return result
	end
end

function p.len(array)
	return #p.clone(array)
end

function p.map(array, iteratee)
	return p._map(iteratee)(array)
end
function p._map(iteratee)
	return function(array)
		local mappingFunction = iteratee
		if type(iteratee) == "string" then
			mappingFunction = function(val) return val[iteratee] end
		end
		local tbl2 = {}
		for k, v in ipairs(array) do
			tbl2[k] = mappingFunction(v)
		end
		return tbl2
	end
end

function p.min(array)
	local min = array[1]
	for _, v in ipairs(array) do
		min = math.min(min, v)
	end
	return min
end

function p.max(array)
	local max = array[1]
	for _, v in ipairs(array) do
		max = math.max(max, v)
	end
	return max
end

function p.padNils(array, padValue, max)
	return p._padNils(padValue, max)(array)
end
function p._padNils(padValue, max)
	return function(array)
		padValue = padValue or ''
		max = max or table.maxn(array)
		local result = p.clone(array)
		for i = 1, max do
			if result[i] == nil then
				result[i] = padValue
			end
		end
		return result
	end
end

function p.partition(array, iteratee)
	return p._partition(iteratee)(array)
end
function p._partition(iteratee)
	return function(array)
		local predicateFn = h.predicate(iteratee)
		local trueResults = {}
		local falseResults = {}
		for i, v in ipairs(array) do
			if predicateFn(v) then
				table.insert(trueResults, v)
			else
				table.insert(falseResults, v)
			end
		end
		return trueResults, falseResults
	end
end

-- returns a copy of tbl with the elements in opposite order (not a deep copy)
function p.reverse(array)
	local tbl2 = {}
	local len = p.len(array)
	for i = len, 1, -1 do
		tbl2[len - i + 1] = array[i]
	end
	return tbl2
end

function p.slice(array, s, e)
	return p._slice(s, e)(array)
end
function p._slice(s, e)
	return function(array)
		local tbl2 = {}
		e = e or p.len(array)
		local j = 1
		for i = s, e do
			tbl2[j] = array[i]
			i = i + 1
			j = j + 1
		end
		return tbl2
	end
end

function p.sortBy(array, iteratees)
	return p._sortBy(iteratees)(array)
end
function p._sortBy(iteratees)
	if type(iteratees) ~= "table" then
		iteratees = {iteratees}
	end
	local comparators = {}
	for i, iteratee in ipairs(iteratees) do
		local mappingFn = h.mapper(iteratee)
		comparators[i] = h.comparator(mappingFn)
	end
	
	return function(array)
		local result = p.clone(array)
		table.sort(result, function(a, b)
			local isEqual, isLessThan
			local i = 1
			repeat
				isEqual, isLessThan = comparators[i](a, b)
				i = i + 1
			until not isEqual or i > #iteratees
			return isLessThan
		end)
		return result
	end
end
function h.comparator(mappingFn)
	return function(a, b)
		a = mappingFn(a)
		b = mappingFn(b)
		return a == b, a < b
	end
end

function p.tail(array)
	local result = {}
	for i in ipairs(array) do
		if i > 1 then
			result[i - 1] = array[i]
		end
	end
	return result
end

function p.take(array, n)
	return p._take(n)(array)
end
function p._take(n)
	return function(array)
		return p.slice(array, 1, n)
	end
end

function p.takeWhile(array, predicate)
	return p._takeWhile(predicate)(array)
end
function p._takeWhile(predicate)
	local predicate = h.predicate(predicate)
	return function(array)
		local result = {}
		local i = 1
		while i <= p.len(array) and predicate(array[i], i) do
			result[i] = array[i]
			i = i + 1
		end
		return result 
	end
end

function p.union(arrays)
	local result = {}
	local seen = {}
	for _, array in ipairs(arrays) do
		for _, value in ipairs(array) do
			if not seen[value] then
				table.insert(result, value)
				seen[value] = true
			end
		end
	end
	return result
end

function p.unique(array)
	local result = {}
	for _, v in ipairs(array) do
		if not p.find(result, p._isEqual(v)) then
			table.insert(result, v)
		end
	end
	return result
end

function p.uniqueBy(array, iteratee)
	return p._uniqueBy(iteratee)(array)
end
function p._uniqueBy(iteratee)
	local mapper = h.mapper(iteratee)
	return function(array)
		local result = {}
		for _, v in ipairs(array) do
			local match = p.find(result, function(val)
				return mapper(val) == mapper(v)
			end)
			if not match then
				table.insert(result, v)
			end
		end
		return result
	end
end

-- Based on https://github.com/lua-stdlib/functional
-- See https://lua-stdlib.github.io/lua-stdlib/modules/std.functional.html#zip
function p.zip(array, padValue)
	local result = {}
	local len = p.len(array)
	for outerk, innerTbl in ipairs(array) do
		innerTbl = p.padNils(innerTbl, "NIL") -- to properly handle sparse arrays
		for k, v in ipairs(innerTbl) do
			result[k] = result[k] or {}
			if v ~= "NIL" then
				result[k][outerk] = v
			end
		end
		if padValue then
			for k in ipairs(result) do
				result[k] = p.padNils(result[k], padValue, len)
			end
		end
	end
	return result
end

p.Schemas = function() return {
	print = {
		singleLine = {
			type = "boolean",
		}
	},
	padNils = {
		padValue = {
			type = "any",
			default = '""',
		},
		max = {
			type = "number",
			default = "table.maxn(array)",
		},
	},
	slice = {
		["start"] = {
			type = "number",
			required = true,
		},
		["end"] = {
			type = "number",
			default = "#array",
		},
	},
	toArray = {
		keys = {
			type = "array",
			items = {
				oneOf = {
					{ type = "string" },
					{ type = "number" },
				},
			},
		},
		padValue = { type = "any" },
	},
	union = {
		arrays = {
			required = true,
			type = "array",
			items = {
				type = "array",
				items = {
					type = "any",
				},
			},
		},
	},
	zip = {
		arrays = {
			type = "array",
			required = true,
			items = { type = "any" },
		},
		padValue = {
			type = "any",
		},
	},
}
end

p.Documentation = function() 
	local propertyShorthand = "<code>{{Sect|property}}</code> shorthand"
	local isMatchShorthand = "<code>{{Sect|isMatch}}</code> shorthand"
	return {
		sections = {
			{
				heading = "Tables",
				section = {
					clone = {
						params = {"tbl"},
						returns = "Creates a shallow clone of <code>tbl</code>.",
						cases = {
							{
								snippet = 1,
								expect = {
									{ foo = {} },
									true, 
									true
								},
							},
						},
					},
					cloneDeep = {
						desc = "Similar to {{Scribunto Manual|lib=mw.clone}} except that it differs in how it handles metatables.",
						params = {"tbl"},
						returns = "Creates a recursive clone of <code>tbl</code>.",
						cases = {
							{
								snippet = 1,
								expect = {
									{ foo = {} },
									true,
									true,
								},
							},
						},
					},
					hasArray = {
						params = {"tbl"},
						returns = "True if the table contains integer keys (or is empty).",
						cases = {
							{
								args = {{1, 2, 3}},
								expect = true,
							},
							{
								args = {{}},
								expect = true,
							},
							{
								args = {{foo = "bar"}},
								expect = false,
							},
							{
								args = {{foo = "bar", "baz"}},
								expect = true,
							},
						}
					},
					hasKey = {
						params = {"tbl", "key"},
						_params = {{"key"}, {"tbl"}},
						returns = "True if <code>tbl[key]</code> is not nil, else false.",
						cases = {
							{
								args = {{"foo", nil, "bar"}, 3},
								expect = true,
							},
							{
								args = {{foo = "bar", baz = "quux"}, "baz"},
								expect = true,
							},
							{
								args = {{"foo", "bar"}, 3},
								expect = false
							},
							{
								args = {{foo = "a", baz = "b"}, "quux"},
								expect = false,
							},
						},
					},
					isArray = {
						params = {"tbl"},
						returns = "True if the table contains '''only''' integer keys (or is empty).",
						cases = {
							{
								args = {{1, 2, 3}},
								expect = true,
							},
							{
								args = {{}},
								expect = true,
							},
							{
								args = {{nil, nil, "foo"}},
								expect = true,
							},
							{
								args = {{[10] = "foo"}},
								expect = true,
							},
							{
								args = {{foo = "bar"}},
								expect = false,
							},
							{
								args = {{foo = "bar", "baz"}},
								expect = false,
							},
						},
					},
					isEmpty = {
						params = {"tbl"},
						returns = "True if <code>tbl</code> has no keys whatsoever",
						cases = {
							{
								args = {{}},
								expect = true,
							},
							{
								args = {{ foo = "bar" }},
								expect = false,
							},
							{
								args = {{nil, "foo"}},
								expect = false,
							},
						}
					},
					isEqual = {
						params = {"tbl", "other"},
						_params = {{"tbl"}, {"other"}},
						returns = "<code>true</code> if <code>tbl</code> deep equals <code>other</code>.",
						cases = {
							{
								args = {
									{ foo = { bar = "baz" } }, 
									{ foo = { bar = "baz" } },
								},
								expect = true,
							},
							{
								args = {
									{ foo = { bar = "baz" } }, 
									{ foo = { bar = "quux" } },
								},
								expect = false,
							},
						}
					},
					invert = {
						params = {"tbl"},
						returns = "A table with the values of <code>tbl</code> as its keys, and vice-versa.",
						cases = {
							{
								args = {{"foo", "bar", baz = "quux"}},
								expect = {
									foo = 1,
									bar = 2,
									quux = "baz"
								},
							},
							{
								desc = "Values will be overwritten if <code>tbl</code> has duplicate values. Overwrite order is not guaranteeed.",
								args = {{ 
									Ganon = "Power", 
									Ganondorf = "Power",
									Link = "Courage",
									Zelda = "Wisdom",
								}},
								expect = {
									Power = "Ganondorf",
									Courage = "Link",
									Wisdom = "Zelda",
								},
							},
						},
					},
					isMatch = {
						desc = "Performs a partial deep comparison between <code>tbl</code> and <code>other</code> to determine if <code>tbl</code> contains equivalent values.",
						params = {"tbl", "source"},
						_params = {{"source"}, {"tbl"}},
						returns = "Returns <code>true</code> if <code>tbl</code> is a match, else false",
						cases = {
							{
								args = {
									{ foo = { bar = "baz", flip = "flop" } },
									{ foo = { bar = "baz" } },
								},
								expect = true,
							},
							{
								args = {
									{1, 2, 3},
									{1, 2},
								},
								expect = true,
							},
							{
								args = {
									{ foo = { bar = "baz" } },
									{ foo = { bar = "quux" } },
								},
								expect = false
							},
						},
					},
					keyOf = {
						params = {"tbl", "value"},
						returns = "First key found whose value is shallow-equal to <code>value</code>, or nil if none found.",
						cases = {
							outputOnly = true,
							{
								args = {{"foo", nil, "bar"}, "bar"},
								expect = 3,
							},
							{
								args = {{foo = "bar", baz = "quux"}, "quux"},
								expect = "baz",
							},
							{
								args = {{"foo", "bar"}, "quux"},
								expect = nil
							},
							{
								desc = "Does not perform deep-equal checks on tables.",
								args = {{{}, {}}, {}},
								expect = nil
							},
						},
					},
					keys = {
						desc = "See also {{Sect|values}} and {{Sect|stringKeys}}.",
						params = {"tbl"},
						returns = "Array of <code>tbl</code> keys.",
						cases = {
							{
								args = {{"foo", "bar", "baz"}},
								expect = {1, 2, 3},
							},
							{
								args = {{ baz = "quux", foo = "bar" }},
								expect = {"foo", "baz"},
							},
							{
								args = {{"foo", bar = "baz", nil, "quux"}},
								expect = {1, 3, "bar"}
							},
						},
					},
					mapValues = {
						params = {"tbl", "iteratee"},
						returns = "Creates a table with the same keys as <code>tbl</code> and values generated by running each value of <code>tbl</code> thru iteratee.",
						cases = {
							{
								snippet = 1,
								expect = { arg1 = "foo", arg2 = "bar"}
							},
							{
								desc = propertyShorthand,
								args = {
									{
										Link = {
											Triforce = "Courage",
										},
										Zelda = {
											Triforce = "Wisdom"
										},
									},
									"Triforce",
								},
								expect = {
									Link = "Courage",
									Zelda = "Wisdom",
								},
							},
						},
					},
					merge = {
						desc = "Recursively merges tables.",
						params = {"tbl", "..." },
						returns = "<code>tbl</code> with merged values. Subsequent sources overwrite key assignments of previous sources.",
						cases = {
							{
								snippet = 1,
								expect = {
									flib = "flob",
									foo = {
										bar = {"noot", "flob"},
										baz = "noot",
										wibble = "wobble",
									},
								}
							},
							{
								desc = "Common use: merging keys into new table.",
								args = {
									{}, 
									{ flib = "flob" }, 
									{ wibble = "wobble" },
								},
								expect = {
									flib = "flob",
									wibble = "wobble",
								},
							},
						}
					},
					print = {
						params = {"tbl", "singleLine"},
						returns = "<code>tbl</code> pretty-printed as a string.",
						cases = {
							outputOnly = true,
							{
								desc = "Prints array items on a single line.",
								args = {{"foo", "bar", "baz"}},
								expect = '{"foo", "bar", "baz"}',
							},
							{
								desc = "Prints single line when tables has one string key.",
								args = {{ foo = "bar" }},
								expect = '{ foo = "bar" }',
							},
							{
								args = {{1, 2, 3, foo = "bar" }},
								expect = '{1, 2, 3, foo = "bar"}',
							},
							{
								desc = "Prints one value per line if more than one string key.",
								args = {{ foo = "bar", flib = "flub" }},
								expect = [[{
								  flib = "flub",
								  foo = "bar",
								}]],
							},
							{
								args = {{1, 2, 3, foo = "bar", flib = "flub" }},
								expect = [[{
								  1,
								  2,
								  3,
								  flib = "flub",
								  foo = "bar",
								}]]
							},
							{
								desc = "Prints one value per line if any are tables.",
								args = {{{1}, {2}}},
								expect = [[{
								  {1},
								  {2},
								}]],
							},
							{
								desc = string.format("Prints one value per line if single-line would exceed %s characters.", MAX_SINGLELINE),
								args = {{"abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"}},
								expect = [[{
								  "abcdefghijklmnopqrstuvwxyz",
								  "abcdefghijklmnopqrstuvwxyz",
								}]]
							},
							{
								desc = "Always prints single-line when <code>singleLine</code> is true",
								args = {{"abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"}, true},
								expect = '{"abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"}'
							},
						},
					},
					printPath = {
						params = {"path"},
						returns = "Property path as a string.",
						cases = {
							outputOnly = true,
							{
								args = {{"foo", 1, "bar", 1}},
								expect = ".foo[1].bar[1]",
							},
							{
								args = {{"foo", '["bar"]'}},
								expect = '.foo["bar"]',
							},
						},
					},
					property = {
						params = {"tbl", "path"},
						_params = {{"path"}, {"tbl"}},
						returns = "The value at <code>path</code> for <code>tbl</code>.",
						cases = {
							outputOnly = true,
							{
								args = {{ foo = {"bar"} }, {"foo", 1}},
								expect = "bar",
							},
							{
								args = {{ foo = {"bar"} }, {"foo", "bar", "baz"}},
								expect = nil,
							},
						},
					},
					size = {
						params = {"tbl"},
						returns = "Total number of keys in <code>tbl</code>.",
						cases = {
							{
								args = {{1, 2, foo = "bar"}},
								expect = 3,
							},
						},
					},
					stringKeys = {
						params = {"tbl"},
						returns = "Array of string keys in <code>tbl</code>",
						cases = {
							{
								args = {{1, 2, foo = "bar", [true] = false}},
								expect = {"foo"},
							},
						},
					},
					ivalues = {
						params = {"tbl"},
						returns = "Array of contiguous, integer-keyed values in <code>tbl</code> starting from 1.",
						cases = {
							{
								args = {{"foo", "bar", wibble = "wobble", [10] = "baz"}},
								expect = {"foo", "bar"},
							},
						},
					},
					toArray = {
						params = {"tbl", "keys", "padValue"},
						_params = {{"keys", "padValue"}, {"tbl"}},
						returns = "An array of all the values in <code>tbl</code>. Order not guaranteed unless <code>keys</code> is specified. If so, the returned array is such that <code>array[i] = utilsTable.keyOf(keys, tbl[i])</code>. Note that the function will return a sparse array when <code>tbl[i] == nil</code>.",
						cases = {
							{
								desc = "Order not guaranteed.",
								args = {
									{ a = "foo", b = 2, c = true },
								},
								expect = {"foo", true, 2},
							},
							{
								desc = "<code>keys</code> param can be used to specify order.",
								args = {
									{ a = "foo", b = 2, c = true },
									{"c", "a", "b"},
								},
								expect = {true, "foo", 2},
							},
							{
								desc = "<code>keys</code> param can be used to grab a subset of the keys.",
								args = {
									{ a = "foo", b = 2, c = true },
									{"a", "b"},
								},
								expect = {"foo", 2},
							},
							{
								desc = "<code>keys</code> param can result in a sparse array if key not in <code>tbl</code>.",
								args = {
									{ a = "foo", b = 2, c = true },
									{"b", "a", "d", "c"},
								},
								expect = {2, "foo", [4] = true},
							},
							{
								desc = "Sparse arrays can be padded with a custom <code>padValue</code>.",
								args = {
									{ a = "foo", b = 2, c = true },
									{"b", "a", "d", "c"},
									""
								},
								expect = {2, "foo", "", true},
							},
						},
					},
				},
			},
			{
				heading = "Arrays",
				section = {
					compact = {
						params = {"array"},
						returns = "Creates an array with falsey values removed.",
						cases = {
							{
								args = {{0, false, 1, ""}},
								expect = {0, 1, ""}
							},
						},
					},
					concat = {
						params = {"array", "..."},
						returns = "Creates a new array concatenating array with any additional arrays and/or values.",
						cases = {
							{
								snippet = 1,
								expect = {1, 2, 3, 4, {5}, 6},
							},
							{
								desc = "Tables with only string keys are treated as single values.",
								args = {{}, {1, 2}, {3, 4, foo = "bar"}, { foo = "quux" }},
								expect = {1, 2, 3, 4, { foo = "quux" }},
							},
						},
					},
					difference = {
						params = {"array", "other"},
						returns = "An array of all the elements in <code>array</code> that are not in <code>other</code>.",
						cases = {
							{
								args = {{"a", "b", "c"}, {"c", "d"}},
								expect = {"a", "b"},
							},
							{
								desc = "Does not deep-compare.",
								args = {{{ foo = "bar" }}, {{ foo = "bar" }}},
								expect = {{ foo = "bar" }},
							}
						},
					},
					dropWhile = {
						params = {"array", "predicate"},
						_params = {{"predicate"}, {"array"}},
						returns = "Creates a slice of <code>array</code> excluding elements dropped from the beginning. Elements are dropped until <code>predicate</code> returns falsey.",
						cases = {
							{
								snippet = 1,
								expect = {"ALttP", "LA", "OoT"},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ game = "SS", hasMasterSword = true },
										{ game = "ALBW", hasMasterSword = true },
										{ game = "TFH", hasMasterSword = false },
										{ game = "BotW", hasMasterSword = true },
									},
									"hasMasterSword",
								},
								expect = {
									{ game = "TFH", hasMasterSword = false },
									{ game = "BotW", hasMasterSword = true },
								},
							},
							{
								snippet = 2,
								expect = {},
							},
						},
					},
					dropRightWhile = {
						params = {"array", "predicate"},
						_params = {{"predicate"}, {"array"}},
						returns = "Creates a slice of <code>array</code> excluding elements dropped from the end. Elements are dropped until <code>predicate</code> returns falsey.",
						cases = {
							{
								snippet = 1,
								expect = {"...", "SS", "ALBW"},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ game = "SS", hasMasterSword = true },
										{ game = "ALBW", hasMasterSword = true },
										{ game = "TFH", hasMasterSword = false },
										{ game = "BotW", hasMasterSword = true },
									},
									"hasMasterSword",
								},
								expect = {
									{ game = "SS", hasMasterSword = true },
									{ game = "ALBW", hasMasterSword = true },
									{ game = "TFH", hasMasterSword = false },
								},
							},
							{
								desc = isMatchShorthand,
								args = {
									{
										{ game = "SS", system = "console" },
										{ game = "ALBW", system = "handheld" },
										{ game = "TFH", system = "handheld" },
										{ game = "BotW", system = "console" },
									},
									{ system = "console" },
								},
								expect = {
									{ game = "SS", system = "console" },
									{ game = "ALBW", system = "handheld" },
									{ game = "TFH", system = "handheld" },
								},
							},
						},
					},
					keyBy = {
						params = {"array", "iteratee"},
						_params = {{"iteratee"}, {"array"}},
						returns = "Creates a table composed of keys generated from the results of running each element of <code>array</code> thru <code>iteratee</code>",
						cases = {
							{
								snippet = 1,
								expect = {
									["TWW Link"] = {
										name = "Link",
										game = "TWW",
										age = 10,
									},
									["TP Link"] = {
										name = "Link",
										game = "TP",
										age = 17,
									},
								},
							},
							{
								desc = propertyShorthand,
								args = {{
									{
										name = "Link",
										age = 10,
									},
									{
										name = "Zelda",
										age = 10,
									},
									{
										name = "Zelda",
										age = 17,
									},
								}, "name"},
								expect = {
									["Link"] = {
										name = "Link",
										age = 10
									},
									["Zelda"] = {
										name = "Zelda",
										age = 17,
									},
								}
							},
						},
					},
					filter = {
						params = {"array", "iteratee"},
						_params = {{"iteratee"}, {"array"}},
						returns = "Iterates over array elements in <code>array</code>, returning an array of all elements <code>iteratee</code> returns truthy for.",
						cases = {
							{
								snippet = 1,
								expect = {"foo", "bar"},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ game = "The Wind Waker", canon = true },
										{ game = "Twilight Princess", canon = true },
										{ game = "Tingle's Rosy Rupeeland", canon = false },
									},
									"canon",
								},
								expect = {
									{ game = "The Wind Waker", canon = true },
									{ game = "Twilight Princess", canon = true },
								},
							},
							{
								desc = isMatchShorthand,
								args = {
									{
										{ game = "The Wind Waker", type = "main" },
										{ game = "Twilight Princess", type = "main" },
										{ game = "Tingle's Rosy Rupeeland", type = "spinoff" },
									},
									{ type = "main" },
								},
								expect = {
									{ game = "The Wind Waker", type = "main" },
									{ game = "Twilight Princess", type = "main" },
								},
							},
						},
					},
					find = {
						params = {"tbl", "iteratee"},
						_params = {{"iteratee"}, {"tbl"}},
						returns = {"The value if found, else <code>nil</code>", "The index of the value found, else <code>nil</code>"},
						cases = {
							outputOnly = true,
							{
								snippet = 1,
								expect = {"bar", 2}
							},
							{
								snippet = 2,
								expect = {nil, nil},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ game = "Tingle's Rosy Rupeeland", canon = false },
										{ game = "The Wind Waker", canon = true },
										{ game = "Breath of the Wild", canon = true },
									},
									"canon"
								},
								expect = {
									{ game = "The Wind Waker", canon = true },
									2,
								},
							},
							{
								desc = isMatchShorthand,
								args = {
									{
										{ 
											game = "Tingle's Rosy Rupeeland", 
											canon = false,
											type = "spinoff",
										},
										{
											game = "Twilight Princess HD",
											canon = true,
											type = "remake",
										},
										{ 
											game = "Breath of the Wild", 
											canon = true,
											type = "main" 
										},
									},
									{ canon = true, type = "main" }
								},
								expect = {
									{ 
										game = "Breath of the Wild", 
										canon = true,
										type = "main" 
									},
									3
								}
							}
						}
					},
					findIndex = {
						params = {"tbl", "iteratee"},
						returns = "The index of the value if found, else <code>nil</code>",
						cases = {
							outputOnly = true,
							{
								snippet = 1,
								expect = 2
							},
							{
								snippet = 2,
								expect = nil,
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ game = "Tingle's Rosy Rupeeland", canon = false },
										{ game = "The Wind Waker", canon = true },
										{ game = "Breath of the Wild", canon = true },
									},
									"canon"
								},
								expect = 2,
							},
							{
								desc = isMatchShorthand,
								args = {
									{
										{ 
											game = "Tingle's Rosy Rupeeland", 
											canon = false,
											type = "spinoff",
										},
										{
											game = "Twilight Princess HD",
											canon = true,
											type = "remake",
										},
										{ 
											game = "Breath of the Wild", 
											canon = true,
											type = "main" 
										},
									},
									{ canon = true, type = "main" }
								},
								expect = 3
							}
						},
					},
					findLast = {
						params = {"array", "iteratee"},
						_params = {{"iteratee"}, {"array"}},
						returns = {
							"The last value found matching <code>iteratee</code>, else <code>nil</code>.", 
							"The index of the value, else <code>nil</code>."
						},
						cases = {
							outputOnly = true,
							{
								snippet = 1,
								expect = {"baz", 3},
							},
							{
								snippet = 2,
								expect = {nil, nil},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ game = "Tingle's Rosy Rupeeland", canon = false },
										{ game = "The Wind Waker", canon = true },
										{ game = "Breath of the Wild", canon = true },
									},
									"canon"
								},
								expect = {
									{ game = "Breath of the Wild", canon = true },
									3,
								},
							},
							{
								desc = isMatchShorthand,
								args = {
									{
										{ 
											game = "Tingle's Rosy Rupeeland", 
											canon = false,
											type = "spinoff",
										},
										{
											game = "Twilight Princess",
											canon = true,
											type = "main",
										},
										{ 
											game = "Breath of the Wild", 
											canon = true,
											type = "main" 
										},
									},
									{ canon = true, type = "main" }
								},
								expect = {
									{ 
										game = "Breath of the Wild", 
										canon = true,
										type = "main" 
									},
									3,
								},
							},
						},
					},
					flatten = {
						params = {"array"},
						returns = "Returns <code>array</code> but flattened a single level deep.",
						cases = {
							{
								args = {{1, {2, {3, 4}}, 5}},
								expect = {1, 2, {3, 4}, 5}
							},
						},
					},
					flatMap = {
						params = {"array", "iteratee"},
						_params = {{"iteratee"}, {"array"}},
						returns = "A flattened array of values created by running each element in <code>array</code> thru <code>iteratee</code> and flattening the mapped results.",
						cases = {
							{
								snippet = 1,
								expect = {1, 1, 2, 2},
							},
						},
					},
					fromPairs = {
						params = {"pairs"},
						returns = "An object composed from key-value <code>pairs</code>.",
						cases = {
							{
								args = {
									{
										{"a", 1},
										{"b", 2},
									},
								},
								expect = {
									a = 1,
									b = 2,
								},
							},
						},
					},
					groupBy = {
						params = {"array", "iteratee"},
						_params = {{"iteratee"}, {"array"}},
						returns = "A table composed of keys generated from the results of running each element of <code>array</code> thru <code>iteratee</code>. The order of grouped values is determined by the order they occur in <code>array</code>. The corresponding value of each key is an array of elements responsible for generating the key. If a <code>nil</code> key is generated for a given value, that value will be absent from the resulting table.",
						cases = {
							{
								snippet = 1,
								expect = {
									[6] = {6.1, 6.3},
									[4] = {4.2},
								},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{
											page = "Link",
											term = "Hero of Time",
											game = "OoT",
										},
										{
											page = "Link",
											term = "Hero of Winds",
											game = "TWW"
										},
										{
											page = "Princess Zelda",
											term = "Zelda",
											game = "SS",
										},
										{
											someOtherData = "foo",
										},
									},
									"page",
								},
								expect = {
									["Link"] = {
										{
											page = "Link",
											term = "Hero of Time",
											game = "OoT",
										},
										{
											page = "Link",
											term = "Hero of Winds",
											game = "TWW"
										},
									},
									["Princess Zelda"] = {
										{
											page = "Princess Zelda",
											term = "Zelda",
											game = "SS",
										},
									},
								},
							},
						},
					},
					includes = {
						params = {"array", "value"},
						returns = "True if and only if <code>value</code> is in <code>array</code>.",
						cases = {
							{
								args = {{"foo", "bar"}, "foo"},
								expect = true
							},
							{
								args = {{"foo", "bar"}, "baz"},
								expect = false
							},
						},
					},
					intersection = {
						params = {"array", "other"},
						returns = "An array of all the elements that are in both <code>array</code> and <code>other</code>",
						cases = {
							{
								args = {{"a", "b", "c"}, {"b"}},
								expect = {"b"},
							},
							{
								desc = "Does not deep-compare.",
								args = {{{ foo = "bar" }}, {{ foo = "bar" }}},
								expect = {},
							},
						},
					},
					len = {
						params = {"array"},
						returns = "The length of the array. Works with {{Scribunto Manual|frame.args}} and tables loaded thru {{Scribunto Manual|mw.loadData}}.",
						cases = {
							{
								args = {{1, 2, 3, [10] = 10}},
								expect = 3,
							},
						},
					},
					map = {
						params = {"array", "iteratee"},
						_params = {{"iteratee"}, {"array"}},
						returns = "Creates an array of values by running each array element in <code>array</code> thru <code>iteratee</code>.",
						cases = {
							{
								snippet = 1,
								expect = {"true", "false"},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{
											name = "Link",
											triforce = "Courage",
										},
										{
											name = "Zelda",
											triforce = "Wisdom",
										},
										{
											name = "Ganon",
											triforce = "Power"
										},
									},
									"triforce"
								},
								expect = {"Courage", "Wisdom", "Power"},
							},
						},
					},
					min = {
						params = {"array"},
						returns = "The maximum value of <code>array</code>, or nil if empty.",
						cases = {
							{
								args = {{3, 2, 1}},
								expect = 1,
							},
							{
								args = {{}},
								expect = nil,
							},
						},
					},
					max = {
						params = {"array"},
						returns = "The maximum value of <code>array</code>, or nil if empty.",
						cases = {
							{
								args = {{5, 10, 20}},
								expect = 20,
							},
							{
								args = {{}},
								expect = nil,
							},
						},
					},
					padNils = {
						params = {"array", "padValue", "max"},
						_params = {{"padValue", "max"}, {"array"}},
						returns = "Returns a version of <code>array</code> such that nil-valued indices up to and including <code>max</code> are replaced with <code>padValue</code>.",
						cases = {
							{
								args = {{nil, 2, nil, 4}, 0},
								expect = {0, 2, 0, 4},
							},
							{
								args = {{nil, 2, nil, 4}, 0, 1},
								expect = {0, 2, nil, 4},
							},
							{
								args = {{nil, 2, nil, 4}, 0, 6},
								expect = {0, 2, 0, 4, 0, 0},
							},
							{
								args = {{"foo", nil, "baz"}},
								expect = {"foo", "", "baz"},
							},
						},
					},
					partition = {
						params = {"array", "iteratee"},
						_params = {{"iteratee"}, {"array"}},
						returns = {
							"<code>array</code> elements that <code>iteratee</code> returns truthy for.",
							"<code>array</code> elements that <code>iteratee</code> returns falsey for.",
						},
						cases = {
							outputOnly = true,
							{
								snippet = 1,
								expect = {
									{"foo", "quux"},
									{"bar", "baz"},
								},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ game = "The Wind Waker", canon = true },
										{ game = "Twilight Princess", canon = true },
										{ game = "Tingle's Rosy Rupeeland", canon = false },
									},
									"canon",
								},
								expect = {
									{
										{ game = "The Wind Waker", canon = true },
										{ game = "Twilight Princess", canon = true },
									},
									{
										{ game = "Tingle's Rosy Rupeeland", canon = false },
									}
								},
							},
							{
								desc = isMatchShorthand,
								args = {
									{
										{ game = "The Wind Waker", type = "main" },
										{ game = "Twilight Princess", type = "main" },
										{ game = "Tingle's Rosy Rupeeland", type = "spinoff" },
									},
									{ type = "main" },
								},
								expect = {
									{
										{ game = "The Wind Waker", type = "main" },
										{ game = "Twilight Princess", type = "main" },
									},
									{
										{ game = "Tingle's Rosy Rupeeland", type = "spinoff" },
									},
								},
							},
						},
					},
					reverse = {
						params = {"array"},
						returns = "Reverses <code>array</code> so that the first element becomes the last, the second element becomes the second to last, and so on.",
						cases = {
							{
								args = {{1, 2, 3}},
								expect = {3, 2, 1},
							},
							{
								desc = "Ignores non-consecutive integer keys",
								args = {{1, 2, 3, [100] = 100}},
								expect = {3, 2, 1},
							},
						},
					},
					slice = {
						params = {"array", "start", "end"},
						_params = {{"start", "end"}, {"array"}},
						returns = "Creates a slice of <code>array</code> from <code>start</code> up to and including <code>end</code>.",
						cases = {
							{
								args = {{"a", "b", "c"}, 1, 2},
								expect = {"a", "b"},
							},
							{
								args = {{"a", "b", "c"}, 2, nil},
								expect = {"b", "c"},
							},
						}
					},
					sortBy = {
						params = {"array", "iteratees"},
						_params = {{"iteratees"}, {"array"}},
						returns = "An array of elements, sorted in ascending order by the results of running each element in <code>array</code> thru each iteratee. This method performs an <u>unstable</u> sort, that is, it does not guarantee that the original order of equal elements will be preserved.",
						cases = {
							{
								snippet = 1,
								expect = {
									{
										game = "TWW",
										systems = {"GCN", "Wii U"},
									},
									{
										game = "LA",
										systems = {"GB", "GBC", "3DS VC"}
									},
									{
										game = "OoT",
										systems = {"N64", "GCN", "iQue", "Wii VC", "Wii U VC"},
									},
								},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{
											name = "Link",
											age = 10,
										},
										{
											name = "Zelda",
											age = 10
										},
										{
											name = "Zelda",
											age = 17
										},
										{
											name = "Link",
											age = 17
										},
									},
									"name",
								},
								expect = {
									{
										name = "Link",
										age = 10,
									},
									{
										name = "Link",
										age = 17,
									},
									{
										name = "Zelda",
										age = 17,
									},
									{
										name = "Zelda",
										age = 10,
									},
								},
							},
							{
								desc = "Multiple sort criteria",
								args = {
									{
										{
											name = "Link",
											age = 10,
										},
										{
											name = "Zelda",
											age = 10
										},
										{
											name = "Zelda",
											age = 17
										},
										{
											name = "Link",
											age = 17
										},
									},
									{"name", "age"},
								},
								expect = {
									{
										name = "Link",
										age = 10,
									},
									{
										name = "Link",
										age = 17,
									},
									{
										name = "Zelda",
										age = 10,
									},
									{
										name = "Zelda",
										age = 17,
									},
								},
							},
						},
					},
					tail = {
						params = {"array"},
						returns = "Gets all but the first element of <code>array</code>.",
						cases = {
							{
								args = {{1, 2, 3}},
								expect = {2, 3},
							},
							{
								args = {{}},
								expect = {},
							},
						}
					},
					take = {
						params = {"array", "n"},
						_params = {{"n"}, {"array"}},
						returns = "Creates a slice of array with n elements taken from the beginning.",
						cases = {
							{
								args = {{1, 2, 3}, 2},
								expect = {1, 2},
							},
							{
								args = {{1, 2, 3}, 5},
								expect = {1, 2, 3},
							},
							{
								args = {{1, 2, 3}, 0},
								expect = {},
							},
						},
					},
					takeWhile = {
						params = {"array", "predicate"},
						_params = {{"predicate"}, {"array"}},
						returns = "Creates a slice of <code>array</code> with elements taken from the beginning. Elements are taken until <code>predicate</code> returns falsey.",
						cases = {
							{
								snippet = 1,
								expect = {"TLoZ", "TAoL", "ALttP", "LA"},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ game = "TLoZ", is2D = true },
										{ game = "TAoL", is2D = true },
										{ game = "ALttP", is2D = true },
										{ game = "LA", is2D = true },
										{ game = "OoT", is2D = false },
										{ game = "TMC", is2D = true },
									},
									"is2D",
								},
								expect = {
									{ game = "TLoZ", is2D = true },
									{ game = "TAoL", is2D = true },
									{ game = "ALttP", is2D = true },
									{ game = "LA", is2D = true },
								},
							},
							{
								desc = isMatchShorthand,
								args = {
									{
										{ game = "TLoZ", system = "console" },
										{ game = "TAoL", system = "console" },
										{ game = "ALttP", system = "console" },
										{ game = "LA", system = "handheld" },
										{ game = "OoT", system = "console" },
									},
									{ system = "console" },
								},
								expect = {
									{ game = "TLoZ", system = "console" },
									{ game = "TAoL", system = "console" },
									{ game = "ALttP", system = "console" },
								},
							},
						},
					},
					union = {
						params = {"arrays"},
						returns = "An array of unique values, in order, from all given arrays.",
						cases = {
							{
								args = {{{"a", "b", "c"}, {"b"}, {"c", "d"}}},
								expect = {"a", "b", "c", "d"},
							},
							{
								desc = "Does not deep-compare for equality.",
								args = {
									{
										{
											{ foo = "bar" }, 
											{ foo = "bar" },
										},
									}
								},
								expect = {
									{ foo = "bar" },
									{ foo = "bar" },
								},
							},
						},
					},
					unique = {
						params = {"array"},
						returns = "A copy of <code>array</code> but without the duplicate values. Elements are deep-compared. he order of result values is determined by the order they occur in the array.",
						cases = {
							{
								args = {
									{1, 2, 2, {foo = "bar"}, {foo = "quux"}, {foo = "bar"}},
								},
								expect = {1, 2, {foo = "bar"}, {foo = "quux"}},
							},
						},
					},
					uniqueBy = {
						params = {"array", "iteratee"},
						_params = {{"iteratee"}, {"array"}},
						returns = "A copy of <code>array</code> but without the duplicate values. <code>iteratee</code> is invoked for each element in array to generate the criterion by which uniqueness is computed.",
						cases = {
							{
								snippet = 1,
								expect = {
									{ title = "LA", game = "LA" },
									{ title = "OoT", game = "OoT" },
								},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ title = "LA", game = "LA" },
										{ title = "OoT", game = "OoT" },
										{ title = "LADX", game = "LA" },
										{ title = "OoT3D", game = "OoT" },
										{ title = "LANS", game = "LA" },
									},
									"game"
								},
								expect = {
									{ title = "LA", game = "LA" },
									{ title = "OoT", game = "OoT" },
								},
							},
						},
					},
					zip = {
						params = {"arrays", "padValue"},
						returns = [[
							Creates a transposition of <code>arrays</code>. That is, an array of grouped elements, the first of which contains the first elements of the given arrays, the second of which contains the second elements of the given arrays, and so on.
							Should the elements of <code>arrays</code> not be of the same length, the resulting groups can be padded to the same length with <code>padValue</code>.
						]],
						cases = {
							{
								args = {{
									{1, 2},
									{"a", "b"},
									{true, false},
								}},
								expect = {
									{1, "a", true},
									{2, "b", false},
								},
							},
							{
								args = {{
									{1, 2},
									{"a", "b", "c"},
									{true}
								}, ""},
								expect = {
									{1, "a", true},
									{2, "b", ""},
									{"", "c", ""},
								},
							},
							{
								args = {{
									{1, 2},
									{"a", "b", "c"},
									{true}
								}},
								expect = {
									{1, "a", true},
									{2, "b", nil},
									{nil, "c", nil},
								}
							}
						},
					},
				},
			},
		},
	}
end

return p