Lua 成对排列,顺序与编写时相同
Posted
技术标签:
【中文标题】Lua 成对排列,顺序与编写时相同【英文标题】:Lua in pairs with same order as it's written 【发布时间】:2015-09-07 07:39:41 【问题描述】:有没有什么方法可以按照与下面的表格相同的顺序循环遍历表格?
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”这个函数又是基于“成对”的,所以就不行了……
【问题讨论】:
这些值是您想要循环的顺序吗?或者这只是巧合? 我想以与写入相同的顺序循环遍历表“tbl”,所以第一个 gotrough 应该是键“hello”,第二个 2,第三个 50,... 当有人没有意识到订单很重要时出于某种原因重新安排事情时,依赖源内订单会在以后提出问题。如果您需要明确的订单,请明确订单。 我为我的问题添加了另一个可行的解决方案:) 【参考方案1】:在 Lua 中,pair 遍历键的顺序是未指定的。但是,您可以保存在数组样式表中添加项目的顺序并使用ipairs
(它具有在数组中迭代键的定义顺序)。为了帮助解决这个问题,您可以使用元表创建自己的有序表,以便在添加新键时保持键顺序。
EDIT(之前的代码在更新时插入了多个密钥副本)
为此,您可以使用__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)
【讨论】:
作为一项规则,没有人可以对从他们的代码中做出的所有可能的错误推断负责;做某事的错误方法太多了。我已经抽象出搜索,现在删除显然不在循环中,我希望这能让我们俩都满意:) 这对我有用。 =) 谢谢。这是我在 github/etc 上看到的代码吗?我不会对此发表评论(或根本不会考虑太多)。但特别是在 SO 和网站及其目标受众提供的帮助的长尾意图的背景下,我认为解决方案应该尽可能减少“阻碍”。【参考方案2】:没有。表格没有“如源代码中所写”的顺序。 (考虑并非所有键都必须存在于源中。)对于非连续整数键,lua 没有“按顺序”的概念。
如果您想要特定订单,您可以通过某种方式自己手动保留该订单。
如果您的表中没有任何整数键,那么您可以使用它们作为您的订单(并使用 ipairs
循环这些键并将值作为键来获取实际值)。
如果您的原始值是您想要排序的顺序,那么您可以循环和反向映射以获得一个表格,您可以在完成后使用ipairs
进行迭代。
【讨论】:
谢谢,我会走那条路……虽然没有想象中那么好,但如果不可能,这将是 x.x 的单一方式以上是关于Lua 成对排列,顺序与编写时相同的主要内容,如果未能解决你的问题,请参考以下文章
UITableView 使用 Realm 和 Swift 具有多个按字母顺序排列的部分,多个标签与相同的数据连接