【问题标题】:Non numeral indeces and the # never counts?非数字索引和 # 从不计算?
【发布时间】:2014-12-23 19:20:28
【问题描述】:

给定一个具有混合索引的表,例如:

table = {
  foo = 'bar'
  [1] = 'foobar'
}

我的问题是关于 # 的问题,它给出了最后一个索引,该索引在遍历表时没有通过间隙分开。

print(#table) 

将给出输出1

table = {
  foo = 'bar',
  lol = 'rofl',
  [1] = 'some',
  [2] = 'thing',
  [3] = 'anything',
  [4] = 'else'
}
print(#table)

应该打印 4

我能否 100% 确定 # 永远不会被非数字索引分心? 这些索引真的每次都被忽视了吗?

【问题讨论】:

  • 虽然很容易理解你的意思,但最好让你的示例代码可编译。像4 = else 这样的表构造函数显然是非法的。
  • 好的,完成。打字时没注意到。
  • 请允许我编辑您的代码,这不仅仅是else 成为关键字。 [4] = 'else' 看起来不太清晰,不像更常见的语法糖,但它是合法的。

标签: lua indexing lua-table


【解决方案1】:

是的,你可以依靠它(在 lua 5.1 中)。

来自luareference manual

长度运算符由一元运算符# 表示。的长度 一个字符串是它的字节数(也就是字符串的通常含义 每个字符为一个字节时的长度)。

表 t 的长度被定义为任何整数索引 n 使得 t[n] 不是 nil 并且 t[n+1] 是 nil;此外,如果 t[1] 为 nil,则 n 可以是 零。对于从 1 到给定 n 的非零值的常规数组, 它的长度正好是 n,它的最后一个值的索引。如果 数组有“洞”(即其他非零值之间的零值), 那么 #t 可以是任何直接在 nil 值之前的索引 (也就是说,它可以将任何这样的 nil 值视为数组的末尾)。

lua 5.2 允许__len 元方法对表进行操作,这意味着# 可以做其他事情。有关示例,请参阅@kikito 的答案。

【讨论】:

    【解决方案2】:

    唯一的方法是遍历条目并计算它们。使用 ipair 遍历项目并递增计数器,然后返回结果。

    function tablelength(T)
     local count = 0 for _ in pairs(T) do
        count = count + 1 end
     return count 
    end
    

    # 运算符仅适用于哈希表类型。

    见:How to get number of entries in a Lua table?

    【讨论】:

    • 我不想得到桌子的长度,这不是这里的问题。但除此之外,什么是灰台?连google的俄罗斯朋友都不知道。
    • 对不起,我误解了你的问题。我说的是哈希数组..错字。但是你可以使用这个方法来获取最后一个索引。
    • # 明确适用于具有非数字索引的表。
    • 它不适用于具有非数字索引的字段,因为它认为它会计算从最低到 n 或间隙的数字索引。
    【解决方案3】:

    Etan 的答案是正确的,但并不完整。

    在 Lua 中,如果表的元表具有 __len 函数,它将控制 # 运算符吐出的内容。可以定义它,以便考虑非数组键。

    local mt = {__len = function(tbl)
      local len = 0
      for _ in pairs(tbl) do len = len + 1 end
      return len
    end}
    

    这说明了事情:

    local t = {1,2,3,4,foo='bar',baz='qux'}
    
    print(#t) -- 4
    setmetatable(t, mt)
    print(#t) -- 6
    

    如果您真的想确保获得“正确”的类似数组的长度,则必须改用rawlen

    print(rawlen(t)) -- 4, even with the metatable set
    

    编辑:请注意 __len 不像我在 Lua 5.1 上提到的那样工作

    【讨论】:

    • 再次感谢您的指导,但它不符合问题。
    • Lua 5.1 reference manual 总是说,__len 元方法不适用于表(或字符串)...
    • @Sempie:在您提出的问题中,“我能 100% 确定 # 不会被非数字索引分心吗?”。 “绝对永不”的答案是否定的(元方法可以改变它)。我认为这是相关的。
    • 确实,lua 5.2 以与此处相关的方式稍微改变了# 的行为。
    • 关于默认 # (rawlen) 能够被 __len 覆盖的优点。但是,关于 rawlen 的一个说明:它仅适用于具有序列的表。数组是一个实现细节。即使表没有序列,标准实现也可以有数组部分。
    猜你喜欢
    • 2022-08-22
    • 1970-01-01
    • 2010-11-29
    • 1970-01-01
    • 1970-01-01
    • 2014-09-16
    • 1970-01-01
    • 2022-11-02
    • 2013-09-09
    相关资源
    最近更新 更多