You can edit almost every page by Creating an account and confirming your email.

Module:Table: Difference between revisions

From EverybodyWiki Bios & Wiki
WikiMaster (talk | contribs)
m 1 revision imported
 
WikiMasterBot2 (talk | contribs)
m Add new revision
 
Line 2: Line 2:


-- A number of functions, most of them imported from [[wikt:Module:table]], a
-- A number of functions, most of them imported from [[wikt:Module:table]], a
-- spinoff of [[Module:TableTools]].
-- spinoff of [[Module:TableTools]].  


local libraryUtil = require('libraryUtil')
local libraryUtil = require('libraryUtil')
Line 21: Line 21:
end
end
end
end
end
end
local function defaultKeySort(item1, item2)
-- "number" < "string", so numbers will be sorted before strings.
local type1, type2 = type(item1), type(item2)
if type1 ~= type2 then
return type1 < type2
else -- This will fail with table, boolean, function.
return item1 < item2
end
end
end
end
Line 32: Line 42:
local check = _check('keysToList')
local check = _check('keysToList')
check(1, t, 'table')
check(1, t, 'table')
check(2, keySort, 'function', true)
check(2, keySort, { 'function', 'boolean', 'nil' })
end
end
Line 42: Line 52:
end
end
-- Place numbers before strings, otherwise sort using <.
if keySort ~= false then
if not keySort then
keySort = type(keySort) == 'function' and keySort or defaultKeySort
keySort = function(item1, item2)
-- "number" < "string", so numbers will be sorted before strings.
table.sort(list, keySort)
local type1, type2 = type(item1), type(item2)
if type1 ~= type2 then
return type1 < type2
else
return item1 < item2
end
end
end
end
table.sort(list, keySort)
return list
return list
Line 126: Line 127:


--[[
--[[
Recursive deep copy function
Recursive deep copy function.
Preserves identities of subtables.
]]
]]
function p.deepCopy(orig, noMetatable)
local function _deepCopy(orig, includeMetatable, already_seen)
    local orig_type = type(orig)
-- Stores copies of tables indexed by the original table.
    local copy
already_seen = already_seen or {}
    if orig_type == 'table' then
        copy = {}
local copy = already_seen[orig]
        for orig_key, orig_value in pairs(orig) do
if copy ~= nil then
            copy[p.deepCopy(orig_key, noMetatable)] = p.deepCopy(orig_value, noMetatable)
return copy
        end
end
        if not noMetatable then
        setmetatable(copy, p.deepCopy(getmetatable(orig)))
if type(orig) == 'table' then
        end
copy = {}
    else -- number, string, boolean, etc
for orig_key, orig_value in pairs(orig) do
        copy = orig
copy[deepcopy(orig_key, includeMetatable, already_seen)] = deepcopy(orig_value, includeMetatable, already_seen)
    end
end
    return copy
already_seen[orig] = copy
if includeMetatable then
local mt = getmetatable(orig)
if mt ~= nil then
local mt_copy = deepcopy(mt, includeMetatable, already_seen)
setmetatable(copy, mt_copy)
already_seen[mt] = mt_copy
end
end
else -- number, string, boolean, etc
copy = orig
end
return copy
end
end


function p.deepCopy(orig, noMetatable, already_seen)
checkType("deepCopy", 3, already_seen, "table", true)
return _deepCopy(orig, not noMetatable, already_seen)
end


--[[
--[[
Line 163: Line 184:
end
end


--[[
-- This returns the length of a table, or the first integer key n counting from
-- 1 such that t[n + 1] is nil. It is similar to the operator #, but may return
-- a different value when there are gaps in the array portion of the table.
-- Intended to be used on data loaded with mw.loadData. For other tables, use #.
--]]
function p.length(t)
local i = 0
repeat
i = i + 1
until t[i] == nil
return i - 1
end
function p.inArray(arr, valueToFind)
checkType("inArray", 1, arr, "table")
-- if valueToFind is nil, error?
for _, v in ipairs(arr) do
if v == valueToFind then
return true
end
end
return false
end


return p
return p

Latest revision as of 14:59, 14 March 2019


local p = {}

-- A number of functions, most of them imported from [[wikt:Module:table]], a
-- spinoff of [[Module:TableTools]]. 

local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti

local function _check(funcName, expectType)
	if type(expectType) == "string" then
		return function(argIndex, arg, nilOk)
			checkType(funcName, argIndex, arg, expectType, nilOk)
		end
	else
		return function(argIndex, arg, expectType, nilOk)
			if type(expectType) == "table" then
				checkTypeMulti(funcName, argIndex, arg, expectType, nilOk)
			else
				checkType(funcName, argIndex, arg, expectType, nilOk)
			end
		end
	end
end

local function defaultKeySort(item1, item2)
	-- "number" < "string", so numbers will be sorted before strings.
	local type1, type2 = type(item1), type(item2)
	if type1 ~= type2 then
		return type1 < type2
	else -- This will fail with table, boolean, function.
		return item1 < item2
	end
end

--[[
	Returns a list of the keys in a table, sorted using either a default
	comparison function or a custom keySort function.
]]
function p.keysToList(t, keySort, checked)
	if not checked then
		local check = _check('keysToList')
		check(1, t, 'table')
		check(2, keySort, { 'function', 'boolean', 'nil' })
	end
	
	local list = {}
	local index = 1
	for key, value in pairs(t) do
		list[index] = key
		index = index + 1
	end
	
	if keySort ~= false then
		keySort = type(keySort) == 'function' and keySort or defaultKeySort
		
		table.sort(list, keySort)
	end
	
	return list
end

--[[
	Iterates through a table, with the keys sorted using the keysToList function.
	If there are only numerical keys, sparseIpairs is probably more efficient.
]]
function p.sortedPairs(t, keySort)
	local check = _check('keysToList')
	check(1, t, 'table')
	check(2, keySort, 'function', true)
	
	local list = p.keysToList(t, keySort, true)
	
	local i = 0
	return function()
		i = i + 1
		local key = list[i]
		if key ~= nil then
			return key, t[key]
		else
			return nil, nil
		end
	end
end

--[[
	Returns true if all keys in the table are consecutive integers starting at 1.
--]]
function p.isArray(t)
	checkType("isArray", 1, t, "table")
	
	local i = 0
	for k, v in pairs(t) do
		i = i + 1
		if t[i] == nil then
			return false
		end
	end
	return true
end

-- { "a", "b", "c" } -> { a = 1, b = 2, c = 3 }
function p.invert(array)
	checkType("invert", 1, array, "table")
	
	local map = {}
	for i, v in ipairs(array) do
		map[v] = i
	end
	
	return map
end

--[[
	{ "a", "b", "c" } -> { ["a"] = true, ["b"] = true, ["c"] = true }
--]]
function p.listToSet(t)
	checkType("listToSet", 1, t, "table")
	
	local set = {}
	for _, item in ipairs(t) do
		set[item] = true
	end
	
	return set
end

--[[
	Recursive deep copy function.
	Preserves identities of subtables.
	
]]
local function _deepCopy(orig, includeMetatable, already_seen)
	-- Stores copies of tables indexed by the original table.
	already_seen = already_seen or {}
	
	local copy = already_seen[orig]
	if copy ~= nil then
		return copy
	end
	
	if type(orig) == 'table' then
		copy = {}
		for orig_key, orig_value in pairs(orig) do
			copy[deepcopy(orig_key, includeMetatable, already_seen)] = deepcopy(orig_value, includeMetatable, already_seen)
		end
		already_seen[orig] = copy
		
		if includeMetatable then
			local mt = getmetatable(orig)
			if mt ~= nil then
				local mt_copy = deepcopy(mt, includeMetatable, already_seen)
				setmetatable(copy, mt_copy)
				already_seen[mt] = mt_copy
			end
		end
	else -- number, string, boolean, etc
		copy = orig
	end
	return copy
end

function p.deepCopy(orig, noMetatable, already_seen)
	checkType("deepCopy", 3, already_seen, "table", true)
	
	return _deepCopy(orig, not noMetatable, already_seen)
end

--[[
	Concatenates all values in the table that are indexed by a number, in order.
	sparseConcat{ a, nil, c, d }  =>  "acd"
	sparseConcat{ nil, b, c, d }  =>  "bcd"
]]
function p.sparseConcat(t, sep, i, j)
	local list = {}
	
	local list_i = 0
	for _, v in require("Module:TableTools").sparseIpairs(t) do
		list_i = list_i + 1
		list[list_i] = v
	end
	
	return table.concat(list, sep, i, j)
end

--[[
-- This returns the length of a table, or the first integer key n counting from
-- 1 such that t[n + 1] is nil. It is similar to the operator #, but may return
-- a different value when there are gaps in the array portion of the table.
-- Intended to be used on data loaded with mw.loadData. For other tables, use #.
--]]
function p.length(t)
	local i = 0
	repeat
		i = i + 1
	until t[i] == nil
	return i - 1
end

function p.inArray(arr, valueToFind)
	checkType("inArray", 1, arr, "table")
	
	-- if valueToFind is nil, error?
	
	for _, v in ipairs(arr) do
		if v == valueToFind then
			return true
		end
	end
	
	return false
end

return p

This module "Table" is from Wikipedia if otherwise notified