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 17: | Line 17: | ||
local infinity = math.huge | local infinity = math.huge | ||
local checkType = libraryUtil.checkType | local checkType = libraryUtil.checkType | ||
local | |||
-- Define a unique value to represent NaN. This is because NaN cannot be used as a table key. | |||
local nan = {} | |||
--[[ | --[[ | ||
Line 23: | Line 25: | ||
-- 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 31: | ||
------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ||
--]] | --]] | ||
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 | ||
-- if | -- 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 lim = select('#', ...) | |||
if lim == 0 then | |||
error("no arguments passed to 'union'", 2) | |||
end | |||
local ret, trackArrays = {}, {} | |||
for i = 1, lim do | |||
local t = select(i, ...) | |||
checkType('union', i, t, 'table') | |||
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 | |||
break | |||
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 lim = select('#', ...) | |||
end | if lim == 0 then | ||
error("no arguments passed to 'valueUnion'", 2) | |||
end | |||
local vals, ret = {}, {} | |||
for i = 1, lim do | |||
local t = select(i, ...) | |||
checkType('valueUnion', i, t, 'table') | |||
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 lim = select('#', ...) | ||
for k, v in pairs(t) do | if lim == 0 then | ||
ret[k] = v | error("no arguments passed to 'intersection'", 2) | ||
end | |||
local ret, track, pairCounts = {}, {}, {} | |||
for i = 1, lim do | |||
local t = select(i, ...) | |||
checkType('intersection', i, t, 'table') | |||
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 158: | ||
--[[ | --[[ | ||
------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ||
-- | -- 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 lim = select('#', ...) | |||
if lim == 0 then | |||
local ret | error("no arguments passed to 'valueIntersection'", 2) | ||
for i, | end | ||
local vals, ret = {}, {} | |||
for i = 1, lim do | |||
local t = select(i, ...) | |||
checkType('valueIntersection', i, t, 'table') | |||
if | 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 | end | ||
end | 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 | |||
ret[#ret + 1] = val | |||
end | |||
end | end | ||
return ret | return ret | ||
end | end | ||
--[[ | --[[ | ||
Line 126: | Line 230: | ||
checkType('affixNums', 2, prefix, 'string', true) | checkType('affixNums', 2, prefix, 'string', true) | ||
checkType('affixNums', 3, suffix, 'string', true) | checkType('affixNums', 3, suffix, 'string', true) | ||
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 244: | ||
table.sort(nums) | table.sort(nums) | ||
return nums | return nums | ||
end | end | ||
Line 229: | Line 283: | ||
local key = nums[i] | local key = nums[i] | ||
return key, t[key] | return key, t[key] | ||
end | end | ||
end | end | ||
Line 243: | Line 295: | ||
------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ||
--]] | --]] | ||
function p.size(t) | function p.size(t) | ||
checkType('size', 1, t, 'table') | checkType('size', 1, t, 'table') | ||
Line 251: | Line 302: | ||
end | end | ||
return i | return i | ||
end | end | ||
return p | return p |