Objective: Write a function to check if a table is a mixed table. A mixed table is just a table that acts as both an array and as a dictionary.
The central question is actually this: Can you guarantee that next(tbl, #tbl)
will always return the first non-sequential key in the table?
For context:
-
An array is a list of values. In Lua, the values don’t really matter, but the index is always sequential and numerical, starting at 1:
{2, 4, 45, 2, 1}
-
A dictionary (sometimes called a map or hash map) uses non-sequential and typically non-numeric keys. For instance:
{points = 32, kills = 10, deaths = 3}
-
And thus, a mixed table might look like this:
{3, 56, 2, points = 43, kills = 10}
My attempt is this: Write three helper methods (IsEmpty
, IsArray
, and IsDictionary
) which will return true
only if they are exclusively true (i.e. IsArray
will not return true if it’s also a dictionary). Then, simply check if the array is both a dictionary and an array. Boom. Done.
Here’s what I have so far:
local function IsEmpty(tbl)
return (next(tbl) == nil)
end
-- This is the potential game-stopper:
local function IsArray(tbl)
return ((#tbl ~= 0) and (next(tbl, #tbl) == nil))
end
local function IsDictionary(tbl)
return ((#tbl == 0) and (next(tbl) == nil))
end
local function IsMixed(tbl)
return (IsArray(tbl) and IsDictionary(tbl))
end
Set your eyes on the IsArray
function. This is the crux of everything here. That function is relying on the assumed fact that next
will always start with the sequential array indices (starting at 1), and continue sequentially before hitting any other keys. IF THAT IS TRUE, then this will work. However, I have no idea how to prove it. It seems to work from the little testing I’ve done, but I’m not sure.
Can anyone verify this? Or point out any flaws in my logic so far?
If the answer is “no, you cannot guarantee this behavior,” then I also ask: Is there any other way to check for a mixed table?