*Luaで良く作る関数 ~table編~ [#x86ba688] -[[table.empty>#table_empty]] -[[table.elemn>#table_elemn]] -[[table.in_key>#table_in_key]] -[[table.in_value>#table_in_value]] -[[table.keys>#table_keys]] -[[table.values>#table_values]] -[[table.map>#table_map]] -[[table.filter>#table_filter]] -[[table.dcopy>#table_deeepcopy_recursive]] -[[table.scopy>#table_shallowcopy]] -[[配列タイプのテーブルの高速複製>#talbe_numtype_shallowcopy]] -[[table.merges>#table_merges]] -[[table.unpack (Lua5.1用)>#table_unpack]] -[[table.pack (Lua5.1用)>#table_pack]] &aname(table_empty); **table.empty [#v0d29c8d] #sh(lua){{ -- テーブルが空かどうかの判定 -- 引数にnilを渡しても「空」とみなす。 function table.empty(tbl) if tbl==nil then return true end return not next (tbl) end }} &aname(table_elemn); **table.elemn [#p6fb257c] #sh(lua){{ -- テーブルに実際に存在する要素数(=num of elements) -- 「#」や「table.getn」「table.maxn」ではテーブルの要素数は調べられないので必要となる。 function table.elemn(tbl) local n = 0 for _ in pairs (tbl) do n = n + 1 end return n end }} &aname(table_in_key); **table.in_key [#qe875447] #sh(lua){{ -- 対象のテーブルのキーに、指定のkeyが存在するかどうか。 function table.in_key (tbl, key) for k, v in pairs (tbl) do if k==key then return true end end return false end }} &aname(table_in_value); **table.in_value [#zc99510e] #sh(lua){{ -- 対象のテーブルの値に、指定のvalが存在するかどうか。 function table.in_value (tbl, val) for k, v in pairs (tbl) do if v==val then return true end end return false end }} &aname(table_keys); **table.keys [#pa87fd7a] #sh(lua){{ -- 対象のテーブルのキーだけを抽出し、新たなテーブルとして得ます。 function table.keys (tbl) local u = {} for i, v in pairs (tbl) do table.insert (u, i) end return u end }} &aname(table_values); **table.values [#pa87fd7a] #sh(lua){{ -- 対象のテーブルの値だけを抽出し、新たなテーブルとして得ます。 function table.values (tbl) local u = {} for i, v in pairs (tbl) do table.insert (u, v) end return u end }} &aname(table_unique); **table.unique [#w6b71518] #sh(lua){{ -- 対象のテーブルの重複した値を除いた、新たなテーブルを返す。但し、キータイプの要素はそのまま残す。 function table.unique (tbl) local check = {} local res = {} -- 整数型だけユニーク化 for i, v in ipairs(tbl) do if not(check[v]) then check[v] = true res[1+#res] = v end end -- キータイプはそのまま残す for k, v in pairs (tbl) do -- 整数以外 if not (type(k)=="number" and k%1==0) then res[k] = v end end return res end }} -使い方 #sh(lua){{ local tbl = {1, 2, 3, 3.0, 4.0, 5, 1} local unique_tbl = table.unique(tbl) --> { 1, 2, 3, 4, 5 } local tbl = {1,2,3,[1.5]=2, 3,2,1,2,3,3,5, a=5,b=5} local unique_tbl = table.unique(tbl) --> { 1, 2, 3, 5, [1.5]=2, a=5, b=5 } キータイプはそのまま残り、それ以外の重複要素はカット }} &aname(table_map); **table.map [#vf1c03dc] #sh(lua){{ -- 対象のテーブルの各要素に対して、func(key, value)を実行し、関数実行結果を格納する。 -- 元のテーブルの値は変化せず、新たなテーブルが返される。 function table.map(tbl, func) local ret_tbl = {} for k, v in pairs (tbl) do ret_tbl[k] = func (k, v) end return ret_tbl end }} -使い方 #sh(lua){{ local tbl = {1,2,k=4 } local tbl2 = table.map( tbl , function(k, v) return v*v end ) -- 全ての要素を2乗した新たなテーブルを得る }} &aname(table_filter); **table.filter [#ydfc1f1a] #sh(lua){{ -- テーブル内で「func(k, v)を満たす」ものだけを新たなテーブルとして返す -- func : テーブルtblの各判定に利用する関数 -- tbl : 対象のテーブル。(i型でもk型でも混合でもOK) -- 戻り値 funcの条件によってフィルタリングされたテーブル。各要素はシャロウコピー function table.filter(tbl, func) local res = {} for i, v in ipairs(tbl) do if func(i, v) then res[1+#res] = v --高速 end end for k, v in pairs(tbl) do if func(k, v) then -- 整数以外がキーの要素 if not (type(k)=="number" and k%1==0) then res[k] = v end end end return res end }} -使い方 #sh(lua){{ local old_tbl = {1,10,30,a=20,b=30} local new_tbl = table.filter(old_tbl, function(k, v) return v < 21 end) --> { 1, 10, b=20 } }} &aname(table_deeepcopy_recursive); **table.dcopy [#za5236fa] #sh(lua){{ -- テーブルの再帰的なディープコピー(deepcopy)を新たなテーブルとして返します。~ -- メタテーブルもコピーされます。 function table.dcopy(tbl) local orig_type = type(tbl) local copy if orig_type == 'table' then copy = {} for orig_key, orig_value in next, tbl, nil do copy[table.dcopy(orig_key)] = table.dcopy(orig_value) end setmetatable(copy, table.dcopy(getmetatable(tbl))) else -- number, string, boolean, etc copy = tbl end return copy end }} -使い方 #sh(lua){{ local a = {1, 2, 3, { b=3,d=4, {c=a} } } local b = {__iter = "abc", e = 33 } setmetatable(a, b) local c = table.dcopy(a) }} &aname(table_shallowcopy); **table.scopy [#t1429da5] #sh(lua){{ --テーブルのシャロウコピー(shallowcopy)を新たなテーブルとして返します。~ --メタテーブルはコピーされません。 function table.scopy(tbl) local orig_type = type(tbl) local copy if orig_type == 'table' then copy = {} for orig_key, orig_value in pairs(tbl) do copy[orig_key] = orig_value end else -- number, string, boolean, etc copy = tbl end return copy end }} &aname(talbe_numtype_shallowcopy); **配列タイプ(indexタイプ)のテーブルの高速複製 [#q682b8aa] #sh(lua){{ --一番良く利用するNumberタイプのテーブルのシャロウコピーの場合、関数すら不要です。 local old_tbl = {5,8,"abc"} local new_tbl = { unpack(old_tbl) } -- テーブルをリスト化してテーブルとすることでシャロウコピーとなる。5.2以降だと { table.unpack(old_tbl) } }} &aname(table_merges); **table.merges [#wf2a3e76] #sh(lua){{ -- ... :テーブル。2つ以上テーブルを渡す。 -- 整数indexの要素のものは、連結。シャロウコピー -- キータイプものものは、重複していたら、後で渡したテーブルで上書き。 -- 返り値 : 連結された新たなテーブル function table.merges (...) local r = {} for _, l in ipairs ({...}) do if type(l) == "table" then -- 整数がキーの要素 for _, v in ipairs (l) do table.insert (r, v) end -- 整数以外がキーの要素 for k, v in pairs (l) do if not (type(k)=="number" and k%1==0) then r[k] = v end end end end return r end }} -使い方 #sh(lua){{ local mergetbl = table.merges( { 1,2,3,k=5,{1,2} }, { 10,2 }, { a=50,k=10 } ) -- > { 1, 2, 3, { 1, 2 }, 10, 2, a=50, k=10 } }} &aname(table_unpack); **table.unpack (Lua5.1用) [#d37acffe] #sh(lua){{ -- lua5.2と同じ記述が可能なように、unpackをtable.unpackに複製 if not table.unpack then table.unpack = unpack end }} &aname(table_pack); **table.pack (Lua5.1用) [#t2b7b166] #sh(lua){{ -- lua5.2と同じ記述が可能なように、table.packを作成 if not table.pack then function table.pack (...) return { n=select('#',...); ...} end end }}