Lua Table pairs输出顺序问题 (版本差异 解决数字索引间断并兼容字符串索引)

时间:2024-02-01 18:35:28

问题标签:

  Lua Table 迭代器;Lua Table 输出顺序; Lua Table 顺序输出;Lua Table 数字索引 字符串索引;Lua Table pairs;

问题背景:

  使用pairs输出table时,其输出顺序与通常认知不相符.

  例如使用pairs输出如下table

T = {
    [1] = "1",
    [2] = "1",
    [3] = "1",
    [4] = "1",
    [5] = "1",
    
    [10] = "1",
    [20] = "1",
    [30] = "1",
    [40] = "1",
    [50] = "1",
    
    [11] = "1",
    [12] = "1",
    [13] = "1",
    q = "1",
    [14] = "1",
    w = "1",
    [15] = "1",
    e = "1",
    r = "1",
    t = "1",
    y = "1",
}

for k,v in pairs(T) do
    print(k)
end

我们通常认为:输出结果会是先顺序输出12345,再乱序输出其它

但是恰巧 在lua 5.1.5 都是乱序

 

 

经测试在lua 5.1.5,如果想与通常认为相符,那么就不能显示指定索引值,只能隐式指定索引值,就是把上述table改成这样:

 

T = {
    "1",
    "1",
    "1",
    "1",
    "1",
    
    [10] = "1",
    [20] = "1",
    [30] = "1",
    [40] = "1",
    [50] = "1",
    
    [11] = "1",
    [12] = "1",
    [13] = "1",
    q = "1",
    [14] = "1",
    w = "1",
    [15] = "1",
    e = "1",
    r = "1",
    t = "1",
    y = "1",
}

 

但是这种解决办法,显然让人无法接受,让人窒息.所以今天研究了一下解决办法

 

目标:

  使用迭代器输出Table时,首先顺序输出数字索引(允许数字索引间断),最后输出字符串索引

问题解决:

  灵感来源于<Programming In Lua>中的代码:

 

function pairsByKeys(t)
    local a = {}

    for n in pairs(t) do
        a[#a + 1] = n
    end

    table.sort(a)

    local i = 0
        
    return function()
        i = i + 1
        return a[i], t[a[i]]
    end
end

for key, value in pairsByKeys(表) do      
     
end 

 

  但是这个还差点意思,当table中包含字符串索引时,会报错.我们期望能和pairs一样兼容字符串索引.我们强化一下,如下:

function spairs(t)
    local num_key_table = {}
    local string_key_table = {}
    
    for k,v in pairs(t) do
        if type(k) == "number" then
            num_key_table[#num_key_table + 1] = k
        else
            string_key_table[k] = v
        end
    end
    
    table.sort(num_key_table)
    
    local i = 0
    
    return function()
        if  i < #num_key_table then
            i = i + 1
            return num_key_table[i], t[num_key_table[i]]
        else
            for k,v in pairs(string_key_table) do
                string_key_table[k] = nil
                return k,v
            end
        end
    end
end

for k,v in spairs(T) do
    print(k)
end

对比:

还有改进的地方,欢迎指导