在 Lua 中迭代对象中的值(按顺序)

Nil*_*les 4 lua

我正在为我的问题寻找一个简单的解决方案。我有这个代码:

local Month = {
    Jan = 1, Feb = 2, Mar = 3, Apr = 4,
    May = 5, Jun = 6, Jul = 7, Aug = 8,
    Sep = 9, Oct = 10, Nov = 11, Dec = 12
}
...
p.main = function()
    local text = ""
    for k,v in pairs(Month) do
        text = text .. " " .. k;
    end
    return text;
end
Run Code Online (Sandbox Code Playgroud)

当我打电话时,p.main()我希望它Jan Feb ... Dec(按顺序)打印,尽管它打印Jan Mar Apr Oct Feb Dec Nov Aug Jul May Jun Sep在我看来是相当随机的顺序。

提前致谢!

LMD*_*LMD 6

Lua中表的哈希部分是无序的。字符串键位于哈希部分。这就是您观察“随机”顺序的原因。

只需将Month表从月份名称到数字的映射转换为从数字到名称的映射,即将其翻转并将其转换为列表:

local monthnames = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}
Run Code Online (Sandbox Code Playgroud)

ipairs那么你可以方便地使用(而不是)按顺序迭代它pairs- 甚至更重要的是,你的p.main函数简化为对 的单个调用table.concat,这是一个用于连接字符串列表的 Lua 内置函数,并且由于该值是常量,因此你可以预先计算一下:

local space_separated_monthnames = table.concat(monthnames, " ")
function p.main()
    return space_separated_monthnames
end
Run Code Online (Sandbox Code Playgroud)

这不会添加前导空格,但我认为无论如何都不是有意的。

如果您需要保留旧的查找,没问题 - 您可以从列表中生成它:

local monthnumber = {}
for i, name in ipairs(monthnames) do
    monthnumber[name] = i
end
Run Code Online (Sandbox Code Playgroud)

另请注意,循环中的字符串连接是 Lua 中的反模式,因为它既效率低下(二次与线性,至少在构建更长的字符串时非常明显),又不方便编写(例如,您的代码发出可能不需要的前导空格)并且需要更多代码才能不发出它)。一般来说,如果您看到类似以下内容:

local str = vals[1]
for i = 2, #vals do
    str = str .. separator .. vals[i]
end
Run Code Online (Sandbox Code Playgroud)

将其重构为

local str = table.concat(vals, separator)
Run Code Online (Sandbox Code Playgroud)

无论是为了性能还是可读性。