Lua 成对出现,顺序和它写的一样 [英] Lua in pairs with same order as it's written

查看:14
本文介绍了Lua 成对出现,顺序和它写的一样的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有什么办法可以像下面这样的表格按照写入的顺序循环遍历?

Is there any way to loop trough a table like the one below in the same order as it's written?

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

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

What I mean is that when I use "in pairs" I'll get a different order everytime I execute my code ...

我正在寻找这样的东西:

I'm searching for something like this:

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"再次基于成对",它不起作用......

But because the function "get_keys" is based on "in pairs" again, it won't work ...

推荐答案

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

In Lua, the order that pairs iterates through the keys is unspecified. However you can save the order in which items are added in an array-style table and use ipairs (which has a defined order for iterating keys in an array). To help with that you can create your own ordered table using metatables so that the key order will be maintained when new keys are added.

EDIT(较早的代码在更新时插入了密钥的多个副本)

EDIT (earlier code inserted multiple copies of the key on updates)

要做到这一点,您可以使用 __newindex,只要索引尚未添加到表中,我们就会调用它.ordered_add 方法更新、删除或存储隐藏表_keys_values 中的键.请注意 __newindex 在我们更新键时也将始终被调用,因为我们没有将值存储在表中而是将它存储在隐藏"表中 _keys_values.

To do this you can use __newindex which we be called so long as the index is not added yet to the table. The ordered_add method updates, deletes, or stores the key in the hidden tables _keys and _values. Note that __newindex will always be called when we update the key too since we didn't store the value in the table but instead stored it in the "hidden" tables _keys and _values.

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

Note however that we cannot use any key in this table, the key name "_keys" will overwrite our hidden table so the safer alternative is to use the ordered_table.insert(t, key, value) ordered_table.index(t, key) and ordered_table.remove(t, key) methods.

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) 

这篇关于Lua 成对出现,顺序和它写的一样的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆