How to check if lua table contains only consecutive numeric indices?

How to write a function that determines if table argument is true?

isArray({1, 2, 4, 8, 16}) -> true isArray({1, "two", 3, 4, 5}) -> true isArray({1, [3]="two", [2]=3, 4, 5}) -> true isArray({1, dictionaryKey = "not an array", 3, 4, 5}) -> false 

I see no way to find out if the number keys are the only ones.

+7
source share
7 answers

ipair iterates over indices 1..n, where n + 1 is the first index with a zero value
pairs are repeated on all keys.
if there are more keys than consecutive indexes, then this cannot be an array.

So all you have to do is see if the number of elements in pairs(table) equals the number of elements in ipairs(table)
The code can be written as follows:

 function isArray(tbl) local numKeys = 0 for _, _ in pairs(tbl) do numKeys = numKeys+1 end local numIndices = 0 for _, _ in ipairs(tbl) do numIndices = numIndices+1 end return numKeys == numIndices end 

I'm new to Lua, so there may be a built-in function to reduce the calculations of numKeys and numIndices for simple function calls.

+3
source

EDIT: Here's a new way to test arrays that I discovered most recently. For each element returned by pairs , it just checks that the nth element on it is not nil . As far as I know, this is the fastest and most elegant way to test an array.

 local function isArray(t) local i = 0 for _ in pairs(t) do i = i + 1 if t[i] == nil then return false end end return true end 
+15
source

By "true array", I suppose, you mean a table whose keys are only numbers. To do this, check the type of each key in your table. Try the following:

 function isArray(array) for k, _ in pairs(array) do if type(k) ~= "number" then return false end end return true --Found nothing but numbers ! end 
+2
source

Here I take it upon myself, using #array to detect a gap or stop when too many keys are read:

 function isArray(array) local count=0 for k,_ in pairs(array) do count=count+1 if (type(k) ~= "number" or k < 1 or k > #array or count > #array or math.floor(k) ~= k) then return false end end if count ~= #array then return false end return true end 
0
source

I wrote this code for another similar question recently:

 ---Checks if a table is used as an array. That is: the keys start with one and are sequential numbers -- @param t table -- @return nil,error string if t is not a table -- @return true/false if t is an array/isn't an array -- NOTE: it returns true for an empty table function isArray(t) if type(t)~="table" then return nil,"Argument is not a table! It is: "..type(t) end --check if all the table keys are numerical and count their number local count=0 for k,v in pairs(t) do if type(k)~="number" then return false else count=count+1 end end --all keys are numerical. now let see if they are sequential and start with 1 for i=1,count do --Hint: the VALUE might be "nil", in that case "not t[i]" isn't enough, that why we check the type if not t[i] and type(t[i])~="nil" then return false end end return true end 
0
source

Note: as @eric points out, pairs are not defined to repeat in a specific order. Therefore, this is not a valid answer.

The following is enough: it checks that the keys are consistent from 1 to the end:

 local function isArray(array) local n = 1 for k, _ in pairs(array) do if k ~= n then return false end n = n + 1 end return true end 
0
source

Iterate from 0 to the number of elements and check for the presence of all elements with a counter index. If it is not an array, some indices will be skipped in sequence.

-one
source

All Articles