How can I check if a lua table contains only sequential numeric indices?

前端 未结 7 2189
时光取名叫无心
时光取名叫无心 2021-02-06 06:07

How can I write a function that determines whether it\'s table argument is a true array?

isArray({1, 2, 4, 8, 16}) -> true
isArray({1, \"two\", 3, 4, 5}) ->         


        
相关标签:
7条回答
  • 2021-02-06 06:24

    Note: as @eric points out, pairs is not defined to iterate in a specific order. Hence this is no valid answer.

    The following should be sufficient; it checks that the keys are sequential from 1 until 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 讨论(0)
  • 2021-02-06 06:25

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

    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
    
    0 讨论(0)
  • 2021-02-06 06:26

    Iterate from 0 to the number of elements, and check if all elements with the counter's index exist. If it's not an array, some indexes will miss in the sequence.

    0 讨论(0)
  • 2021-02-06 06:30

    ipairs iterates over indices 1..n, where n+1 is the first integer index with a nil value
    pairs iterates over all keys.
    if there are more keys than there are sequential indices, then it cannot be an array.

    So all you have to do is see if the number of elements in pairs(table) is equal to 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 pretty new to Lua, so there might be some builtin function to reduce the numKeys and numIndices calculations to simple function calls.

    0 讨论(0)
  • 2021-02-06 06:31

    Here's my take on this, using #array to detect a gap or stop when too many keys have been 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 讨论(0)
  • 2021-02-06 06:41

    I wrote this code for another similar question lately:

    ---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's 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's why we check the type
            if not t[i] and type(t[i])~="nil" then return false end
        end
        return true
    end
    
    0 讨论(0)
提交回复
热议问题