Editing Module:TableTools
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 8: | Line 8: | ||
------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ||
--]] | --]] | ||
local p = {} | local p = {} | ||
Line 16: | Line 14: | ||
local floor = math.floor | local floor = math.floor | ||
local infinity = math.huge | local infinity = math.huge | ||
local | -- Define a unique value to represent NaN. This is because NaN cannot be used as a table key. | ||
local nan = {} | |||
--[[ | --[[ | ||
Line 23: | Line 22: | ||
-- isPositiveInteger | -- isPositiveInteger | ||
-- | -- | ||
-- This function returns true if the given | -- This function returns true if the given number is a positive integer, and false | ||
-- if not. Although it doesn't operate on tables, it is included here as it is | -- if not. Although it doesn't operate on tables, it is included here as it is | ||
-- useful for determining whether a given table key is in the array part or the | -- useful for determining whether a given table key is in the array part or the | ||
Line 29: | Line 28: | ||
------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ||
--]] | --]] | ||
function p.isPositiveInteger( | function p.isPositiveInteger(num) | ||
if type(num) == 'number' and num >= 1 and floor(num) == num and num < infinity then | |||
return true | |||
else | |||
return false | |||
end | |||
end | end | ||
--[[ | --[[ | ||
------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ||
-- | -- union | ||
-- | -- | ||
-- This | -- This returns the union of the key/value pairs of n tables. If any of the tables | ||
-- | -- contain different values for the same table key, the table value is converted | ||
-- | -- to an array holding all of the different values. | ||
-- | ------------------------------------------------------------------------------------ | ||
--]] | |||
function p.union(...) | |||
local ret, trackArrays = {}, {} | |||
for i = 1, select('#', ...) do | |||
local t = select(i, ...) | |||
for k, v in pairs(t) do | |||
local retKey = ret[k] | |||
if retKey == nil then | |||
ret[k] = v | |||
elseif retKey ~= v then | |||
if trackArrays[k] then | |||
local array = ret[k] | |||
local valExists | |||
for _, arrayVal in ipairs(array) do | |||
if arrayVal == v then | |||
valExists = true | |||
end | |||
end | |||
if not valExists then | |||
array[#array + 1] = v | |||
ret[k] = array | |||
end | |||
else | |||
ret[k] = {ret[k], v} | |||
trackArrays[k] = true | |||
end | |||
end | |||
end | |||
end | |||
return ret | |||
end | |||
--[[ | |||
------------------------------------------------------------------------------------ | |||
-- valueUnion | |||
-- | |||
-- This returns the union of the values of n tables, as an array. For example, for | |||
-- the tables {1, 3, 4, 5, foo = 7} and {2, bar = 3, 5, 6}, union will return | |||
-- {1, 2, 3, 4, 5, 6, 7}. | |||
------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ||
--]] | --]] | ||
function p. | function p.valueUnion(...) | ||
local vals, ret = {}, {} | |||
end | for i = 1, select('#', ...) do | ||
local t = select(i, ...) | |||
for k, v in pairs(t) do | |||
if type(v) == 'number' and tostring(v) == '-nan' then | |||
v = nan -- NaN cannot be a table key, so use a proxy variable. | |||
end | |||
vals[v] = true | |||
end | |||
end | |||
for val in pairs(vals) do | |||
if val == nan then | |||
-- This ensures that we output a NaN when we had one as input, although | |||
-- they may have been generated in a completely different way. | |||
val = 0/0 | |||
end | |||
ret[#ret + 1] = val | |||
end | |||
return ret | |||
end | |||
--[[ | --[[ | ||
------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ||
-- | -- intersection | ||
-- | -- | ||
-- This returns | -- This returns the intersection of the key/value pairs of n tables. Both the key | ||
-- | -- and the value must match to be included in the resulting table. | ||
------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ||
--]] | --]] | ||
function p. | function p.intersection(...) | ||
local ret = {} | local ret, track, pairCounts = {}, {}, {} | ||
for k, v in pairs(t) do | local lim = select('#', ...) | ||
ret[k] = v | for i = 1, lim do | ||
local t = select(i, ...) | |||
for k, v in pairs(t) do | |||
local trackVal = track[k] | |||
if trackVal == nil then | |||
track[k] = v | |||
pairCounts[k] = 1 | |||
elseif trackVal == v then | |||
pairCounts[k] = pairCounts[k] + 1 | |||
end | |||
end | |||
end | |||
for k, v in pairs(track) do | |||
if pairCounts[k] == lim then | |||
ret[k] = v | |||
end | |||
end | end | ||
return ret | return ret | ||
Line 66: | Line 140: | ||
--[[ | --[[ | ||
------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ||
-- | -- valueIntersection | ||
-- | -- | ||
-- This | -- This returns the intersection of the values of n tables, as an array. For | ||
-- | -- example, for the tables {1, 3, 4, 5, foo = 7} and {2, bar = 3, 5, 6}, | ||
-- | -- intersection will return {3, 5}. | ||
------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ||
--]] | --]] | ||
function p. | function p.valueIntersection(...) | ||
local vals, ret = {}, {} | |||
local lim = select('#', ...) | |||
for i = 1, lim do | |||
local t = select(i, ...) | |||
for k, v in pairs(t) do | |||
if type(v) == 'number' and tostring(v) == '-nan' then | |||
v = nan -- NaN cannot be a table key, so use a proxy variable. | |||
end | |||
if | local valCount = vals[v] or 0 | ||
vals[v] = valCount + 1 | |||
end | |||
end | |||
for val, count in pairs(vals) do | |||
if count == lim then | |||
if val == nan then | |||
-- This ensures that we output a NaN when we had one as input, although | |||
-- they may have been generated in a completely different way. | |||
val = 0/0 | |||
end | end | ||
end | ret[#ret + 1] = val | ||
end | |||
end | end | ||
return ret | return ret | ||
end | end | ||
--[[ | --[[ | ||
Line 100: | Line 182: | ||
--]] | --]] | ||
function p.numKeys(t) | function p.numKeys(t) | ||
local isPositiveInteger = p.isPositiveInteger | local isPositiveInteger = p.isPositiveInteger | ||
local nums = {} | local nums = {} | ||
Line 123: | Line 204: | ||
--]] | --]] | ||
function p.affixNums(t, prefix, suffix) | function p.affixNums(t, prefix, suffix) | ||
prefix = prefix or '' | prefix = prefix or '' | ||
suffix = suffix or '' | suffix = suffix or '' | ||
local pattern = '^' .. prefix .. '([1-9]%d*)' .. suffix .. '$' | local pattern = '^' .. prefix .. '([1-9]%d*)' .. suffix .. '$' | ||
local nums = {} | local nums = {} | ||
for k, v in pairs(t) do | for k, v in pairs(t) do | ||
Line 149: | Line 218: | ||
table.sort(nums) | table.sort(nums) | ||
return nums | return nums | ||
end | end | ||
Line 202: | Line 230: | ||
--]] | --]] | ||
function p.compressSparseArray(t) | function p.compressSparseArray(t) | ||
local ret = {} | local ret = {} | ||
local nums = p.numKeys(t) | local nums = p.numKeys(t) | ||
Line 220: | Line 247: | ||
--]] | --]] | ||
function p.sparseIpairs(t) | function p.sparseIpairs(t) | ||
local nums = p.numKeys(t) | local nums = p.numKeys(t) | ||
local i = 0 | local i = 0 | ||
Line 229: | Line 255: | ||
local key = nums[i] | local key = nums[i] | ||
return key, t[key] | return key, t[key] | ||
end | end | ||
end | end | ||
end | end | ||
return p | return p |