成双成对的Lua [英] Lua in pairs with same order as it's written
问题描述
是否有任何方法可以像下面这样循环遍历下面的表?
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 ...
我正在搜索如下内容:
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中,未指定通过键进行配对的配对顺序.但是,您可以将添加项的顺序保存在数组样式表中,并使用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 (earlier code inserted multiple copies of the key on updates)
要执行此操作,可以使用__newindex
,只要尚未将索引添加到表中,就可以使用__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屋!