Module:ListUtil

local range = function (i, j, k) local z = {} for x = i, j or i, k or (i <= j and 1 or -1) do   z[#z + 1] = x  end return z end

local generate = function (n, f) local z = {} for i = 1, n do   z[i] = f(i) end return z end

local array; do local select = select array = function (x, rank, ...) local z = {} if select('#', ...) == 0 then for i = 1, rank do     z[i] = x    end else for i = 1, rank do     z[i] = array(x, ...) end end return z end; end

local any = function (t, pr) for i = 1, #t do   if pr(t[i], i) then return true end end return false end

local all = function (t, pr) for i = 1, #t do   if not pr(t[i], i) then return false end end return true end

local none = function (t, pr) for i = 1, #t do   if pr(t[i], i) then return false end end return true end

local count = function (t, x) local z = 0 for i = 1, #t do   if t[i] == x then z = z + 1 end end return z end

local count_if = function (t, pr) local z = 0 for i = 1, #t do   if pr(t[i], i) then z = z + 1 end end return z end

local find = function (t, x) for i = 1, #t do    if t[i] == x then return i, t[i] end end end

local find_if = function (t, pr) for i = 1, #t do   if pr(t[i], i) then return i, t[i] end end end

local rfind = function (t, x) for i = #t, 1, -1 do    if t[i] == x then return i, t[i] end end end

local rfind_if = function (t, pr) for i = #t, 1, -1 do   if pr(t[i], i) then return i, t[i] end end end

local equal = function (t1, t2) if #t1 == #t2 then for i = 1, #t1 do     if t1[i] ~= t2[i] then return false end end return true end return false end

local compare = function (t1, t2) for i = 1, math.min(#t1, #t2) do   local a, b = t1[i], t2[i] if a < b then return -1 elseif a > b then return 1 end end return #t1 < #t2 and -1 or #t1 > #t2 and 1 or 0 end

local reverse = function (t) local z = {} for i = #t, 1, -1 do   z[#z + 1] = t[i] end return z end

local reverse_self = function (t) for i = 1, #t / 2 do   local j = #t + 1 - i    t[i], t[j] = t[j], t[i] end return t end

local sub = function (t, i, j) j = j or #t if i < 0 then i = i + #t + 1 end if j < 0 then j = j + #t + 1 end local z = {} for k = i, j do   z[#z + 1] = t[k] end return z end

local map = function (t, f) local z = {} for i = 1, #t do   z[i] = f(t[i], i)  end return z end

local map_self = function (t, f) for i = 1, #t do    t[i] = f(t[i], i)  end return t end

local zip = function (t1, t2, op) local z = {} for i = 1, #t1 do   z[i] = op(t1[i], t2[i]) end return z end

local select = function (t, pr) local z = {} for i = 1, #t do   if pr(t[i], i) then z[#z + 1] = t[i] end end return z end

local concat = function (t1, t2) local z = {} for i = 1, #t1 do   z[i] = t1[i] end for i = 1, #t2 do   z[#z + 1] = t2[i] end return z end

local concat_self = function (t1, t2) for i = 1, #t2 do   t1[#t1 + 1] = t2[i] end return t1 end

local to_set = function (t) local z = {} for i = 1, #t do   z[t[i]] = true end return z end

local reduce = function (t, op, z) if z ~= nil then for i = 1, #t do     z = op(z, t[i]) end else z = t[1] for i = 2, #t do     z = op(z, t[i]) end end return z end

local group_by = function (t, f) local z = {} for i = 1, #t do   local v = t[i] local k = f(v, i)   if not z[k] then z[k] = {} end z[k][#z[k] + 1] = v end return z end

return { range = range, generate = generate, array = array,

any = any, all = all, none = none, count = count, count_if = count_if,

find = find, find_if = find_if, rfind = rfind, rfind_if = rfind_if,

equal = equal, compare = compare,

reverse = reverse, reverse_self = reverse_self, sub = sub, map = map, map_self = map_self, zip = zip, select = select, concat = concat, concat_self = concat_self, to_set = to_set,

reduce = reduce, group_by = group_by, }