Replace count_values with count_objects

This commit is contained in:
Lars Mueller 2021-07-07 17:32:33 +02:00
parent 35081f3e4b
commit b5e7f331c4
2 changed files with 26 additions and 23 deletions

@ -1,6 +1,7 @@
local assert, next, pairs, pcall, error, type, table_insert, table_concat, string_format, string_match, setfenv, math_huge, loadfile, loadstring local assert, next, pairs, pcall, error, type, table_insert, table_concat, string_format, string_match, setfenv, math_huge, loadfile, loadstring
= assert, next, pairs, pcall, error, type, table.insert, table.concat, string.format, string.match, setfenv, math.huge, loadfile, loadstring = assert, next, pairs, pcall, error, type, table.insert, table.concat, string.format, string.match, setfenv, math.huge, loadfile, loadstring
local count_values = modlib.table.count_values
local count_objects = modlib.table.count_objects
-- Build a table with the succeeding character from A-Z -- Build a table with the succeeding character from A-Z
local succ = {} local succ = {}
@ -15,7 +16,7 @@ end
local _ENV = {} local _ENV = {}
setfenv(1, _ENV) setfenv(1, _ENV)
function write(object, write) function write(value, write)
local reference = {"A"} local reference = {"A"}
local function increment_reference(place) local function increment_reference(place)
if not reference[place] then if not reference[place] then
@ -29,9 +30,9 @@ function write(object, write)
end end
local references = {} local references = {}
local to_fill = {} local to_fill = {}
for value, count in pairs(count_values(object)) do for value, count in pairs(count_objects(value)) do
local type_ = type(value) local type_ = type(value)
if count >= 2 and ((type_ == "string" and #reference + 2 >= #value) or type_ == "table") then if count >= 2 and (type_ ~= "string" or #reference + 2 >= #value) then
local ref = table_concat(reference) local ref = table_concat(reference)
write(ref) write(ref)
write"=" write"="
@ -116,28 +117,28 @@ function write(object, write)
error("unsupported type: " .. type_) error("unsupported type: " .. type_)
end end
end end
local fill_root = to_fill[object] local fill_root = to_fill[value]
if fill_root then if fill_root then
-- Root table is circular, must return by named reference -- Root table is circular, must return by named reference
dump(object) dump(value)
write"return " write"return "
write(references[object]) write(references[value])
else else
-- Root table is not circular, can directly start writing -- Root table is not circular, can directly start writing
write"return " write"return "
dump(object) dump(value)
end end
end end
function write_file(object, file) function write_file(value, file)
return write(object, function(text) return write(value, function(text)
file:write(text) file:write(text)
end) end)
end end
function write_string(object) function write_string(value)
local rope = {} local rope = {}
write(object, function(text) write(value, function(text)
table_insert(rope, text) table_insert(rope, text)
end) end)
return table_concat(rope) return table_concat(rope)

@ -337,24 +337,26 @@ function deep_foreach_any(table, func)
visit(table) visit(table)
end end
-- Recursively counts occurences of values in a table -- Recursively counts occurences of objects (non-primitives including strings) in a table.
-- Also counts primitive values like boolean and number function count_objects(value)
-- Does not count NaN, because that doesn't work as a table index
function count_values(value)
local counts = {} local counts = {}
local function count_values_(value) if value == nil then
-- Ignore NaN -- Early return for nil
if value ~= value then return end return counts
end
local function count_values(value)
local type_ = type(value)
if type_ == "boolean" or type_ == "number" then return end
local count = counts[value] local count = counts[value]
counts[value] = (count or 0) + 1 counts[value] = (count or 0) + 1
if not count and type(value) == "table" then if not count and type_ == "table" then
for k, v in pairs(value) do for k, v in pairs(value) do
count_values_(k) count_values(k)
count_values_(v) count_values(v)
end end
end end
end end
count_values_(value) count_values(value)
return counts return counts
end end