Module:HashUtil

Lua metamodule containing higher-order functions for non-sequence tables.

* `t`: Table which contains arbitrary key-value pairs.
* `f`: Function which accepts a value from a table as its first argument and the value's corresponding key as its second argument.
* `pr`: Predicate which accepts a value from a table as its first argument and the value's corresponding key as its second argument. Only truthiness of the return value is considered.
* `op`: Function which accepts two table elements.

## Generation

* **from\_lists (ks, vs)**

Creates a table from a list of keys and a list of values. Later duplicate keys take precedence.
* **from\_pairs (s, g)**

Creates a table by calling `g` on each element of the sequence `s` and using its first two return values as a key-value pair.
* **generate (s, g)**

Returns `{[s[1]] = g(s[1]), [s[2]] = g(s[2]), ..., [s[#s]] = g(s[#s])}`.
## Counting

* **any (t, pr)**

Returns true if `pr` is true for any element of `t`.
* **all (t, pr)**

Returns true if `pr` is true for all elements of `t`.
* **none (t, pr)**

Returns true if `pr` is true for none of the elements of `t`.
* **count (t, x)**

Returns the number of elements of `t` that compare equal to `x`.
* **count\_if (t, pr)**

Returns the number of elements of `t` that satisfy `pr`.
## Searching

* **find (t, x)**

Returns the key-value pair of any of the table's elements that compares equal to `x`, or `nil` if none can be found.
* **find\_if (t, pr)**

Returns the key-value pair of any of the table's elements that satisfies `pr`, or `nil` if none can be found.
## Transformation

* **map (t, f)**

Returns a new table with the results of calling `f` on each element of `t`.
* **map\_self (t, f)**

Replaces every element of `t` with the result of calling `f` on it. Returns `t`.
* **zip (t1, t2, op)**

Returns a new table with the results of calling `op` on each element of `t1` and the corresponding element of `t2` with the same key.
* **select (t, pr)**

Returns a new table containing only the elements of `t` that satisfy `pr`.
* **merge (t1, t2)**

Returns a new table containing key-value pairs from both tables. `t2` takes precedence.
* **merge\_self (t1, t2)**

Adds all key-value pairs from `t2` to `t1`. Returns `t1`.
* **invert (t)**

Returns a new table with keys becoming values and values becoming keys. Duplicate keys are overwritten in an arbitrary order.
* **keys (t)**

Returns a sequence containing the keys of the table in an arbitrary order.
* **values (t)**

Returns a sequence containing the values of the table in an arbitrary order.
* **to\_lists (t)**

Returns `keys(t), values(t)`. The orders from the two sequences are guaranteed to be the same.
## Other

* **sorted\_pairs (t)**

Returns a generator which iterates through the key-value pairs of `t`, sorted by keys with `<`.
Equivalent to `sorted_pairs(t, function (v1, v2, k1, k2) return k1 < k2 end)`.
* **sorted\_pairs (t, g)**

Returns a generator which iterates through the key-value pairs of `t`, sorted by `g`, which accepts the values of two pairs to compare followed by their corresponding keys.

```
local pairs = pairs

local from\_lists = function (ks, vs)
 local z = {}
 for i = 1, #ks do
 z[ks[i]] = vs[i]
 end
 return z
end

local from\_pairs = function (s, g)
 local z = {}
 for i = 1, #s do
 local k, v = g(s[i])
 z[k] = v
 end
 return z
end

local generate = function (s, g)
 local z = {}
 for i = 1, #s do
 z[s[i]] = g(s[i])
 end
 return z
end

local any = function (t, pr)
 for k, v in pairs(t) do
 if pr(v, k) then
 return true
 end
 end
 return false
end

local all = function (t, pr)
 for k, v in pairs(t) do
 if not pr(v, k) then
 return false
 end
 end
 return true
end

local none = function (t, pr)
 for k, v in pairs(t) do
 if pr(v, k) then
 return false
 end
 end
 return true
end

local count = function (t, x)
 local z = 0
 for \_, v in pairs(t) do
 if v == x then
 z = z + 1
 end
 end
 return z
end

local count\_if = function (t, pr)
 local z = 0
 for k, v in pairs(t) do
 if pr(v, k) then
 z = z + 1
 end
 end
 return z
end

local find = function (t, x)
 for k, v in pairs(t) do
 if v == x then
 return k, v
 end
 end
end

local find\_if = function (t, pr)
 for k, v in pairs(t) do
 if pr(v, k) then
 return k, v
 end
 end
end

local map = function (t, f)
 local z = {}
 for k, v in pairs(t) do
 z[k] = f(v, k)
 end
 return z
end

local map\_self = function (t, f)
 for k, v in pairs(t) do
 t[k] = f(v, k)
 end
 return t
end

local zip = function (t1, t2, op)
 local z = {}
 for k, v in pairs(t1) do
 z[k] = op(v, t2[k])
 end
 return z
end

local select = function (t, pr)
 local z = {}
 for k, v in pairs(t) do
 if pr(v, k) then
 z[k] = v
 end
 end
 return z
end

local merge = function (t1, t2)
 local z = {}
 for k, v in pairs(t1) do
 z[k] = v
 end
 for k, v in pairs(t2) do
 z[k] = v
 end
 return z
end

local merge\_self = function (t1, t2)
 for k, v in pairs(t2) do
 t1[k] = v
 end
 return t1
end

local invert = function (t)
 local z = {}
 for k, v in pairs(t) do
 z[v] = k
 end
 return z
end

local keys = function (t)
 local z = {}
 for k in pairs(t) do
 z[#z + 1] = k
 end
 return z
end

local values = function (t)
 local z = {}
 for \_, v in pairs(t) do
 z[#z + 1] = v
 end
 return z
end

local to\_lists = function (t)
 local ks = {}
 local vs = {}
 for k, v in pairs(t) do
 ks[#ks + 1] = k
 vs[#vs + 1] = v
 end
 return ks, vs
end

local sorted\_pairs = function (t, f)
 local ks = keys(t)
 if f then
 table.sort(ks, function (k1, k2)
 return f(t[k1], t[k2], k1, k2)
 end)
 else
 table.sort(ks)
 end
 local i = 0
 return function ()
 i = i + 1
 if i <= #ks then
 return ks[i], t[ks[i]]
 end
 end
end

return {
 from\_lists = from\_lists,
 from\_pairs = from\_pairs,
 generate = generate,

 any = any,
 all = all,
 none = none,
 count = count,
 count\_if = count\_if,

 find = find,
 find\_if = find\_if,

 map = map,
 map\_self = map\_self,
 zip = zip,
 select = select,
 merge = merge,
 merge\_self = merge\_self,
 invert = invert,
 keys = keys,
 values = values,
 to\_lists = to\_lists,

 sorted\_pairs = sorted\_pairs,
}

```