Luaリファレンス 要注意点 ~配列~

index番号は"1"から

  • 配列はLUAではINDEX==1 から始めます。
    様々な関数が、それを前提とした作りになっていますので、
    強引に「0」から開始したりはせず、素直に「1」からにしましょう。

    また、#が配列の長さになりますので、
    a[#a+1] = v
    
    などで、リストの最後に追加というイディオムとなります。

配列の0からのインデックス

  • 配列のインデックスを強引に0からにした例
    days = { [0] = "Sunday", "Monday", "Tuesday", ..... }
    
    というようにインデックス[0]を書いておけば良い。
    arr = { 1,2,3,[0]=0 }
    
    というように、位置はどこでも良い。

    ただし、Luaでは多くの関数が、配列1からのスタートを前提とした設計になっているので、このようなことは避けたほうが賢明

配列の間に"nil"がある場合、#による長さはあてにならない

  • 配列の要素にnilがあると、#は非常にわかりにくいアルゴリズムとなってしまうため
    まともに使えません。
    配列の要素にnilがある場合は、#やipairsを使わないようにしましょう。
    local a = {1,2,3,nil,5,nil}
    print(#a) --> 3
    
    local a = {1,2,3,nil,5}
    a[4] = nil
    print(#a) --> 5
    a[6] = nil
    print(#a) --> 3
    a[6] = 6
    print(#a) --> 3
    
    local a = {1,2,3,nil,5,nil}
    print(#a) --> 3
    a[6] = 6
    print(#a) --> 6
    a[6] = nil
    print(#a) --> 3
    a[7] = 7
    print(#a) --> 3
    

というように、理解しがたい値が返ってきます。

配列の間に"nil"がある場合、ipairsはそこで終了

  • ipairsがnilで終了してしまうことも、引っかかりやすい挙動です。
    local a = {1,2,3,nil,5}
    for k, v in ipairs(a) do
        print(k, v)
    end
    -- 1 1
    -- 2 2
    -- 3 3
    

配列が空は、「not next (対象テーブル)」と判定

mytable = {};
if not next mytable then
    print "It's empty"
end

関連項目 => table.empty

初期化

  • 最後のカンマは付いていても問題ない
    arr = { 1,2,3, }
    
  • セミコロンを使うことも可能なので、意味的なセパレータ代わりに使うと良い
    arr = { 1,2,3; 10,11,12; }
    

配列タイプ(indexタイプ)のテーブルの高速複製は「newtbl = { unpack(oldtbl) }」

--一番良く利用する配列タイプのテーブルのシャロウコピーの場合、関数すら不要です。
local old_tbl = {5,8,"abc", "あいう"}
local new_tbl = { unpack(old_tbl) } -- テーブルをリスト化してテーブルとすることでシャロウコピーとなる。 5.2以降は { table.unpack(old_tbl) }

indexが-5から5の配列を作成

a = {}
for i=-5, 5 do
    a[i] = 0
end

行列と多次元配列

mt = {}                    --行列の作成
for i=1, N do
    mt[i] = {}       --行
    for j=1, M do
        mt[i][j] = 0
    end
end

デフォルトの値を持つテーブル

  • 簡単版。未知のフィールドは、全てデフォルトの値が0
    function setDefault(t, d)
        local mt = {__index = function() return d end } -- メタテーブルで指定の初期値
        setmetatable(t, mt)
    end
    
    local tab = {x=10, y=20}
    print(tab.x, tab.z) -->10, nil
    
    setDefault(tab, 0)
    print(tab.x, tab.z) -->10, 0
    

  • ガベージ意識版。未知のフィールドは、全てデフォルトの値が0
    local defaults = {}
    setmetatable(defaults, {__mode = "k" } ) -- defaults は弱いキーを持つ。使われていないキーは回収可能とする。
    local mt = {__index = function (t) return defaults[t] end }
    function setDefault(t, d)
        defaults[t] = d  --そのテーブル自身をキーとしてデフォルト値を持つ
        setmetatable(t, mt)
    end
    
    tab = {x=10, y=20}
    print(tab.x, tab.z) -->10, nil
    
    setDefault(tab, 0)
    print(tab.x, tab.z) -->10, 0
    

  • ガベージ意識版&メモ化版。未知のフィールドは、全てデフォルトの値が0
    local metas = {}
    setmetatable(metas, {__mode = "v" })  -- 弱い値にすることで、いざとなれば、使われていないメタテーブルは回収可能とする。
    function setDefault(t, d)
        local mt = metas[d]
        if mt == nil then
            mt = {__index = function() return d end }
            metas[d] = mt   -- 新たなメタテーブルであれば、それをメモ化
        end
        setmetatable(t, mt)
    end
    
    tab = {x=10, y=20}
    print(tab.x, tab.z) -->10, nil
    
    setDefault(tab, 0)
    print(tab.x, tab.z) -->10, 0
    

キューの実装例

 List = {}
  function List.new ()
    return { first = 0, last = -1 }
  end

  function List.pushfirst ( list, value )
    local first = list.first - 1
    list.first = first
    list[first] = value
  end

  function List.pushlast ( list, value )
    local last = list.last + 1
    list.last = last
    list[last] = value
  end

  function List.popfirst ( list )
    local first = list.first
    if first > list.last then error("list is empty!") end
    local value = list[first]
    list[first] = nil
    list.first = list.first + 1
    return value
  end

  function List.poplast ( list )
    local last = list.last
    if list.first > last then error("list is empty!") end
    local value = list[last]
    list[last] = last - 1
    return value
  end

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-01-23 (土) 03:19:35 (852d)