如何检查 lua 表是否只包含顺序数字索引?

问题描述 投票:0回答:8

如何编写一个函数来确定它的表参数是否是真正的数组?

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

我看不到任何方法来确定数字键是否是唯一的键。

arrays dictionary lua lua-table
8个回答
22
投票

编辑:这是我最近发现的一种测试数组的新方法。对于

pairs
返回的每个元素,它只是检查其上的第 n 个项目不是
nil
。据我所知,这是测试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

4
投票

ipairs 迭代索引 1..n,其中 n+1 是具有 nil 值的 first 整数索引
pairs 迭代所有键。
如果键的数量多于顺序索引的数量,则它不能是数组。

所以你要做的就是看看

pairs(table)
中的元素数量是否等于
ipairs(table)

中的元素数量 代码可以写成如下:

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

我对 Lua 还很陌生,所以可能有一些内置函数可以将 numKeys 和 numIndices 计算减少为简单的函数调用。


2
投票

“真正的数组”,我想你指的是一个键仅为数字的表。为此,请检查表中每个键的类型。试试这个:

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

1
投票

注意:正如@eric 指出的那样,pairs 没有定义为按特定顺序迭代。因此,这不是有效的答案。

以下内容就足够了;它检查键是否是从 1 到末尾的顺序:

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
投票

我最近为另一个类似问题编写了这段代码:

---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
投票

这是我对此的看法,使用

#array
来检测间隙或在读取太多键时停止:

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
投票

如果您不关心索引的顺序(或者只想检查非整数键是否存在),请快速破解:

function isArray(t)
    return next(t, #t) == nil
end

希望这比使用

pairs
迭代更有效,因为这会调用
next
一次,而不是每个索引调用一次。


-1
投票

从0迭代到元素个数,并检查是否所有具有计数器索引的元素都存在。如果不是数组,序列中的某些索引将会丢失。

© www.soinside.com 2019 - 2024. All rights reserved.