如何检查给定的表是否是有效的序列?

Bre*_*ain 6 lua

local seq = { 1, 2, 3, 4, 5 } -- obviously, it's a sequence.
local non_seq = { 1, 2, 3, nil, 5 } -- but it's not.
Run Code Online (Sandbox Code Playgroud)

序列的定义:长度运算符

这个问题在《Programming in Lua 4st》第五章中。

如有任何意见,我将不胜感激

Nif*_*fim 2

您链接了答案所需的信息。

Lua 5.3 中的边界定义为:

(border == 0 or t[border] ~= nil) and t[border + 1] == nil
Run Code Online (Sandbox Code Playgroud)

正确的序列只能包含一个边界。然而,为了涵盖其他一些条件,代码确实需要更多的跑腿工作,例如验证索引可以在序列中。

function is_sequence(t)
    local borders = 0

    if t[1] ~= nil then -- all sequences must start at 1.
        for index in pairs(t) do
            if natural_index(index) and t[index + 1] == nil then
                borders = borders + 1
                if borders > 1 then
                  break
                end
            end
        end
    end

    return borders == 1 or valid_no_borders(t) and borders == 0
end

function natural_index(index)
    return type(index) == "number" and index > 0 and math.floor(index) == index
end

function valid_no_borders(t)
    result = true
    for k in pairs(t) do
      if natural_index(k) then
          result = false
          break
      end
    end
    
    return t[1] == nil and result
end
Run Code Online (Sandbox Code Playgroud)
function is_sequence(t)
    local borders = 0

    if t[1] ~= nil then -- all sequences must start at 1.
        for index in pairs(t) do
            if natural_index(index) and t[index + 1] == nil then
                borders = borders + 1
                if borders > 1 then
                  break
                end
            end
        end
    end

    return borders == 1 or valid_no_borders(t) and borders == 0
end

function natural_index(index)
    return type(index) == "number" and index > 0 and math.floor(index) == index
end

function valid_no_borders(t)
    result = true
    for k in pairs(t) do
      if natural_index(k) then
          result = false
          break
      end
    end
    
    return t[1] == nil and result
end
Run Code Online (Sandbox Code Playgroud)

结果

-- Tests
local seqs = {
  { 1, 2, 3, 4, 5 }, -- obviously, it's a sequence.
  { 1, 2, 3, 4, ["potato"] = 5 }, 
  { 1, 2, [3.3] = 3 },
  { [2.2] = 2 },
  { [-1] = -1, [0] = 0, 1, 2, 3 }, 
  {},
}
for _, v in ipairs(seqs) do
    print("seq: ", is_sequence(v))
end

local non_seqs ={
    { 1, 2, 3, nil, 5 }, -- but it's not.
    { [2] = 2 },
}

for _, v in ipairs(non_seqs) do
    print("non_seq: ", is_sequence(v))
end
Run Code Online (Sandbox Code Playgroud)

此方法的优点是仅对每个元素求值一次,如果表不是有效序列,则尽早退出。


  • 哦,我还刚刚注意到,在编写自己的手册定义实现时,数字不一定是自然数,因此像“{1, 2, 3, [5.4] = 'float'}”这样的表在技术上是仍然是一个序列,因此 `{1, 2, 3, [-4] = "negative"}` (2认同)