微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

循环 – 成对的Lua与写入的顺序相同

有没有办法按照下面的表格以与写入的顺序相同的方式循环一个表格?

local tbl = {
    ["hello"] = 1,[2] = 2,[50] = 3,["bye"] = 4,[200] = 5
}

我的意思是,当我使用“成对”时,每次执行代码时我都会得到不同的顺序……

我正在寻找这样的东西:

function get_keys(tbl)
    local rtable = {}
    for k,v in pairs(tbl) do
        table.insert(rtable,k)
    end
    return rtable
end

local keys_of_tbl = get_keys(tbl)
for i = 1,table.getn(keys_of_tbl) do
    --Do something with: tbl[keys_of_tbl[i]]
end

但是因为函数“get_keys”再次基于“成对”,它将无法工作……

解决方法

在Lua中,未指定对遍历键的顺序.但是,您可以保存在数组样式表中添加项的顺序,并使用ipairs(具有在数组中迭代键的已定义顺序).为此,您可以使用元表创建自己的有序表,以便在添加新键时保持键顺序.

编辑(早期代码在更新时插入了密钥的多个副本)

要做到这一点,你可以使用我们被调用的__newindex,只要索引没有添加到表中. ordered_add方法在隐藏表_keys和_values中更新,删除或存储密钥.请注意,当我们更新密钥时,也会始终调用__newindex,因为我们没有将值存储在表中,而是将其存储在“隐藏”表_keys和_values中.

但请注意,我们不能在此表中使用任何键,键名“_keys”将覆盖我们的隐藏表,因此更安全的替代方法是使用ordered_table.insert(t,key,value)ordered_table.index(t,key)和ordered_table.remove(t,key)方法.

ordered_table = {}

function ordered_table.insert(t,k,v)
  if not rawget(t._values,k) then -- new key 
    t._keys[#t._keys + 1] = k
  end
  if v == nil then -- delete key too.
    ordered_table.remove(t,k)
  else -- update/store value
    t._values[k] = v 
  end
end

local function find(t,value)
  for i,v in ipairs(t) do
    if v == value then
      return i
    end
  end
end  

function ordered_table.remove(t,k)
  local v = t._values[k]
  if v ~= nil then
    table.remove(t._keys,find(t._keys,k))
    t._values[k] = nil
  end
  return v
end

function ordered_table.index(t,k)
    return rawget(t._values,k)
end

function ordered_table.pairs(t)
  local i = 0
  return function()
    i = i + 1
    local key = t._keys[i]
    if key ~= nil then
      return key,t._values[key]
    end
  end
end

function ordered_table.new(init)
  init = init or {}
  local t = {_keys={},_values={}}
  local n = #init
  if n % 2 ~= 0 then
    error"in ordered_table initialization: key is missing value"
  end
  for i=1,n/2 do
    local k = init[i * 2 - 1]
    local v = init[i * 2]
    if t._values[k] ~= nil then
      error("duplicate key:"..k)
    end
    t._keys[#t._keys + 1]  = k
    t._values[k] = v
  end
  return setMetatable(t,{__newindex=ordered_table.insert,__len=function(t) return #t._keys end,__pairs=ordered_table.pairs,__index=t._values
    })
end

--- Example Usage:
local t = ordered_table.new{
  "hello",1,-- key,value pairs
  2,2,50,3,"bye",4,200,5
}

print(#t)
print("hello is",t.hello)
print()
for k,v in pairs(t) do  --- Lua 5.2 __pairs Metamethod
  print(k,v)
end
t.bye = nil -- delete that
t[2] = 7 -- use integer keys
print(#t)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐