2015-06-21 47 views
4

有没有什么方法可以按照与写入顺序相同的顺序循环下面的表格?Lua成对写入的顺序相同

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”是基于“成对”再次,它不会工作...

+0

这些值是您想要循环的顺序吗?或者这只是巧合吗? –

+0

我想按照它写入的顺序循环显示表“tbl”,所以第一次通过应该是关键“你好”,第二个2,第三个50,... –

+1

根据内部源代码的顺序,稍后再询问问题当没有意识到这个订单的人因某种原因重新安排事情时。如果您需要明确的订单,请明确订单。 –

回答

4

在Lua中,没有指定对迭代通过键的顺序。但是,您可以保存在阵列样式表中添加项目的顺序,并使用ipairs(它具有用于迭代数组中键的已定义顺序)。为了解决这个问题,您可以使用元表创建自己的有序表,以便在添加新键时保持键顺序。


编辑(前面的代码插在更新密钥的多个副本)

要做到这一点,你可以使用__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) 
+0

作为一项规则,没有人可以对所有可能的不正确的推断负责任;有太多错误的方法来做某件事。我抽象出了搜索,现在删除显然不在一个循环内,我希望这能满足我们两个:) – ryanpattison

+0

这对我很有用。 =)谢谢。这个代码是我在github/etc上看到的。我不会对它进行评论(或者根本就没有多想)。但具体而言,在战略目标和网站及其目标受众提供的帮助的长尾巴意图的背景下,我认为解决方案应尽可能减少“阻碍”。 –

5

号有没有“写在源”以表格。 (考虑到并非所有密钥都必须存在于源代码中。)lua对于非连续的整数密钥没有“按顺序”的概念。

如果您想要特定的订单,您可以通过某种方式手动保存订单。

如果您的表中没有任何整数键,那么您可以将它们用作您的订单(并使用ipairs来循环这些键并将该值编入索引以获取实际值)。

如果您的原始值是您想要排序的顺序,那么您可以循环并反转地图以获取一张表,您可以在完成后使用ipairs进行迭代。

+0

谢谢,我会这样... ...不如它会好,但如果这是不可能的这将是单一的方式xx –

0

我的一个朋友让我这个小功能,工作太细:

function switch_key_val(tbl) 
    local rtbl = {} 
    for k,v in pairs(tbl) do 
     rtbl[v] = k 
    end 
    return rtbl 
end 

这可以这样使用:

local tbl = { 
    ["hello"] = 1, 
    [2] = 2, 
    [50] = 3, 
    ["bye"] = 4, 
    [200] = 5 
} 
local tbl = switch_key_val(tbl) 

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

这给了我同样的结果,每次我执行我的代码

+2

这是'如果你的原始值...'在我的答案中用于记录。 –