【问题标题】:Does `next()` yield in some stable order if only field values are modified?如果只修改字段值,`next()` 是否会以某种稳定的顺序产生?
【发布时间】:2021-02-01 23:53:15
【问题描述】:

我正在生成一个字符串来表示在表格中编码的状态。状态将通过更改某些表条目的值来更改。我永远不会(在下面调用mkName() 之后)在表中添加或删除键。

我希望字符串是表中状态的一种“规范名称”,因此如果我更改表中的值然后将它们改回来,我希望该“名称”再次相同。目前我直接在我的桌子上使用pairs() 来读取它的所有值。该遍历顺序在值变化时是否稳定?

我的代码是这样的

local function mkName(t)
  local name = ""
  for k, v in pairs(t) do name = name .. k .. ":" .. v .. "," end
  return name
end
local state = { a=1, b=2, c=3 }
local name1 = mkName(state)
state.b = 10
local name2 = mkName(state)
state.b = 2
local name3 = mkName(state)
-- Here I want name1 and name3 to be equal
print(name1, name2, name3, name1==name3)

这在我想要的意义上有效并且稳定,但next()pairs() 使用)的官方文档说:

未指定枚举索引的顺序,即使对于数字索引也是如此。 (要按数字顺序遍历表,请使用数字 for 或 ipairs 函数。)

对于后续调用pairs(),迭代顺序可能会改变有什么原因吗?

【问题讨论】:

标签: lua iteration lua-table


【解决方案1】:

我建议你不要依赖没有承诺但可能会意外工作的东西,但要保证你的状态函数有一个稳定的遍历顺序。可以这样做:

-- Iterator to replace pairs():
local function ordered_pairs (t)
    -- Get table keys:
    local keys = {}
    for key, _ in pairs (t) do
        table.insert (keys, key)
    end
    -- Sort them:
    table.sort (keys, function (a, b)
        local type_a, type_b = type (a), type (b)
        return type_a < type_b
            or type_a == type_b and (type_a == 'number' or type_a == 'string') and a < b
            or type_a == type_b and tostring (a) < tostring (b)
    end)
    -- Loop over the sorted keys:
    local counter = 1
    return function()
        local key = keys [counter]
        if key then
            counter = counter + 1
            return key, t [key]
        end
    end
end
            
-- Actually, it's a serialiser:
local function hash (t)
    local serialised = {}
    for key, value in ordered_pairs (t) do
        table.insert (serialised, tostring (key) .. ':' .. tostring (value))
    end
    return table.concat (serialised, ',')
end

-- Test:
local t = {a = 1, b = 2, c = 3}
print ('Stage 1 (b = 2):', hash (t))
t.b = 10
print ('Stage 2 (b = 10):', hash (t))
t.b = 2
print ('Stage 3 (b = 2):', hash (t))

首先对键进行排序(排序功能相当复杂,需要考虑所有可能的键类型)。然后按其键的顺序对表进行迭代。

如果需要,您可以使用表的元表和 __pairs 覆盖带有 ordered_pairs 的表的 pairs

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-15
    相关资源
    最近更新 更多