テーブルユーティリティ
以下のスクリプトを貼り付けると、table.copyとtable.stable_copyの二つのメソッドが追加される。
table.copyはtableをコピーする。コピー対象にテーブルが含まれていたら、それの中身をさらにコピーする。他の言語ではクローンとか言われるような動作をする。
table.stable_sortは、安定ソートを提供する。たぶん。使い方はtable.sortと同じだが、引数に細工をして簡単に使えるようにした。後述。
do -- テーブルをコピーする。 -- テーブルが入っている場合は、そのものではなくてそのコピーを使う。 table.copy = function(t) local res = {} for k, v in pairs(t) do if type(v)=="table" then v = table.copy(v) end res[k] = v end return res end local default_func = function(a, b) -- デフォルトの比較関数 if a>b then return true end return false end table.stable_sort = function(t, func) -- table.sortの安定ソート版 if #t<2 then return false end -- 項目数が1個なら、ソートは発生しない。 -- ソートアルゴリズムを特定 -- funcが文字列ないし数値であれば、それぞれの項目をテーブルとみなし、そのテーブルのfuncと同じキーを比較対象にする。 if type(func)=="string" or type(func)=="number" then local key = func func = function(a, b) if a[key]>b[key] then return true end return false end end -- さらにそうでもなければ、デフォルトの比較関数が使われる。単純な昇順である。 if type(func)~="function" then func = default_func end local temp for max = #t, 2, -1 do for cursor = 1, max-1 do if func(t[cursor], t[cursor+1]) then temp = t[cursor] t[cursor] = t[cursor+1] t[cursor+1] = temp end end end return true end end
table.stable_sortの使い方
table.stable_sort(t)
このようにした場合、tの各項目は数値が期待され、昇順になる。
table.stable_sor(t, "speed")
このようにした場合、tの各項目はtableが期待され、各項目の["speed"]が比較対象になり、安定昇順になる。
RPGのキャラクターを入れて、その速度で行動順を決めるなどに使える。
local func = function(a, b) -- ごちゃごちゃ end table.stable_sort(t, func)
第二引数に関数を渡した場合、その関数が比較に使われる。
比較関数は、二つの引数を取り、boolean型を返すことが期待されている。
boolean型でtrueを返した場合、項目のスワップが発生する。
一度に複数の項目での比較などをする場合は、これを使う。
ちなみに、
local func = function(...) if math.random(2)==1 then return true end return false end
こういう関数を渡した場合、ランダムなシャッフルになるのはみなさんよくご存知。
local func = function(a, b) if (a.speed + math.random(6)) > (b.speed + math.random(6)) then return true end return false end
それぞれのspeed値にそった並べかえが行われるが、乱数の要素も含むなどこんな感じか。