1. 程式人生 > >【學習Lua】ipairs函式和pairs函式之間有什麼區別?

【學習Lua】ipairs函式和pairs函式之間有什麼區別?

  • 變長引數(variable number of arguments)
    Lua函式中傳遞引數可以使用(…)來表示不確定數量的引數。一個函式要訪問變長引數,需要藉由{…}形式來訪問,此時變長引數被轉化為了一個數組。
function add(...)
    local s = 0
    for i,v in ipairs{...} do
        s = s + v
    end
    return s
end

print(add(3, 4, 10, 25, 12))        -- 54

當變長引數中包含nil時,上述的函式計算可能會出問題:

function
add(...) local s = 0 for i,v in ipairs{...} do s = s + v end return s end print(add(3, 4, nil, 25, 12)) -- 7

ipairs遍歷變長引數時,遇到nil時變終止了。
有兩種方法可以避免這個問題:

  • 0x00 select函式
function add_select(...)
    local s = 0
    for i = 1, select('#', ...) do
        local arg = select(i, ...
) if (arg ~= nil) then s = s + arg end end return s end print(add_select(3, 4, nil, 25, 12)) -- 44

官方文件:
select (index, ···)

If index is a number, returns all arguments after argument number index; a negative number indexes from the end (-1 is the last argument). Otherwise, index must be the string “#”, and select returns the total number of extra arguments it received.

如果index是數字,返回index對應的引數;-1表示最後一個引數。否則,index必須是字串“#”,並返回引數的總數。

  • 0x01 pairs函式
function add(...)
    local s = 0
    for i,v in pairs{...} do
        if v ~= nil then
            s = s + v
        end
    end
    return s
end

print(add(3, 4, nil, 25, 12))       -- 44

ipairs函式和pairs函式之間有什麼區別?
先上文件:
ipairs (t)

Returns three values (an iterator function, the table t, and 0) so that the construction

 for i,v in ipairs(t) do body end

will iterate over the key–value pairs (1,t[1]), (2,t[2]), …, up to the first nil value.

ipairs將會迭代key-value結構形如(1, t[1]),(2, t[2]), …直到第一個nil

pairs (t)

If t has a metamethod __pairs, calls it with t as argument and returns the first three results from the call.

Otherwise, returns three values: the next function, the table t, and nil, so that the construction

 for k,v in pairs(t) do body end

will iterate over all key–value pairs of table t.
pairs將會迭代所有的key-value結構。
See function next for the caveats of modifying the table during its traversal.

總結一下,ipairs與pairs的區別在於兩處:
1. 遍歷的範圍

  • ipairs只能用於遍歷key為整數,且key從1開始依次遞增的key-value;
  • pairs可以遍歷所有key-value。

2.有序性

  • ipairs保證遍歷過程以key的順序進行;
  • pairs遍歷是以table中儲存資料的順序進行的。

以table存取資料,應儘量將有序的資料與無序的資料分開儲存在不同的table中。如果由於專案需求不得不維護一個有序與無序混合的table,而遍歷處理時又要求按照順序進行處理。那麼直接通過ipairs和pairs沒辦法滿足需求,這時候需要引入一個的table來儲存遍歷順序。(該方法來自《Lua程式設計》第19章)

重新定義一個迭代器,先將待處理table的key值儲存到一個臨時的sortTable{key1,key2,…}中,然後對其中的元素key進行排序。再按照排序後的sortTable來輸出table的key-value資料。

function pairsByKeys(t, f)      --~ 其中f為可選引數,用於指定排序順序。類似C++中的仿函式
    local a = {}
    for n in pairs(t) do a[#a + 1] = n end
    table.sort(a, f)
    local i = 0
    return function()
        i = i + 1
        return a[i], t[a[i]]
    end
end
--~ 使用上述迭代器:
for k,v in pairsByKeys(inputTable) do
    print(k, v)
end