Lua_第18章Tableライブラリ
4537 ワード
第18章Tableライブラリ
tableライブラリは、tableを操作するいくつかの補助関数から構成されています.彼の主な役割の一つはLuaにおけるarrayの大きさに対して合理的な解釈を与えることである.またlistから削除要素を挿入する関数やarray要素をソートする関数もいくつか用意されています.
18.1配列サイズ
Luaではarrayが最後の非nil要素で終わるとよく仮定している.この伝統的な約束には弊害がある:私たちのarrayにはnil要素を持つことができない.ほとんどのアプリケーションにとって、この制限は問題ではありません.例えば、すべてのarrayに国定的なタイプがある場合です.しかし、arrayはnil要素を持つ必要がある場合があります.この場合、arrayの大きさを明確に示す方法が必要です.
Tableライブラリは、2つの関数がarrayを操作するサイズを定義します.getnは、arrayのサイズを返します.setn、arrayのサイズを設定します.前述したように、この2つの方法はtableの1つの属性に関連しています.tableの1つのドメインにこの属性を保存するか、独立した(weak)tableを使用してtableとこの属性を関連付けます.2つの方法にはそれぞれメリットとデメリットがあるので、tableライブラリではこの2つの方法を使用しています.
通常、tableを呼び出す.setn(t,n)は、tとnを内部(weak)tableに関連付けるtableを呼び出す.getn(t)は、内部tableとtに関連付けられた値を得る.しかしながら、テーブルtに数値nを有するドメインがある場合、setnはこの値を変更し、getnはこの値を返す.Getn関数には、上記の方法でarrayのサイズを返すことができない場合、最初のnil要素が見つかるまでarrayを巡回する元の方法があります.そのため、arrayでtableをずっと使用することができます.getn(t)は正しい結果を得た.例を見てみましょう.
デフォルトでは、setnとgetnは内部テーブルストレージテーブルのサイズを使用します.これはarrayを汚染する余分な元素を使用しないため、最もきれいな選択です.しかしながら、nドメインを使用する方法にもいくつかの利点がある.可変パラメータを持つ関数種では、Luaカーネルはこの方法を使用してarg配列のサイズを設定します.カーネルはライブラリに依存しないため、setnを使用できません.もう1つの利点は、arrayが作成されたときに、上記の例で見たように、彼のサイズを直接初期化できることです.
setnとgetnを使用してarrayのサイズを操作するのは、ドメインnにサイズがあることを知っていても良い習慣です.tableライブラリのすべての関数(sort、concat、insertなど)はこの習慣に従います.実際には、setnを提供してドメインnの値を変更するのは、古いluaバージョンと互換性を持つためであり、この特性は将来のバージョンで変更される可能性があります.安全のため、この特性に依存すると仮定しないでください.getnを使用して配列サイズを取得し、setnを使用して配列サイズを設定してください.
18.2挿入/削除
tableライブラリはlistの任意の場所から要素を挿入および削除する関数を提供します.table.Insert関数はarray指定の位置に要素を挿入し、後ろの他のすべての要素を後ろに移動します.また、insertはarrayのサイズを変更します.例えば、aが配列{10,20,30}である場合、tableが呼び出される.Insert(a,1,15)後,aは{15,10,20,30}となる.よく使用される特殊な場合は、位置パラメータを持たずにinsertを呼び出すと、arrayの最後の位置に要素が挿入されます(したがって、要素の移動は必要ありません).次のコードは、プログラムに行ごとに独立し、すべての行をarrayに保存します.
table.remove関数は、配列内の指定された位置の要素を削除し、この要素を返します.その後の要素はすべて前に移動し、配列のサイズが変わります.位置パラメータ呼び出しがない場合、arrayの最後の要素を削除します.
この2つの関数を使用すると、枝、キュー、両端キューが容易に実現されます.構造をa={}に初期化できます.1つのpush操作はtableに等しい.insert(a,x);1つのpop操作はtableに等しい.remove(a).構造の他端に要素を挿入するにはtableを使用します.insert(a,1,x);削除要素用table.remove(a,1).最後の2つの操作は、要素を往復移動しなければならないため、特に有効ではありません.しかしながら,tableライブラリのこれらの関数はC実装を用いるため,小さな配列(数百要素)にとって効率に問題はない.
18.3ソート
もう一つの役に立つ関数はtableです.sort.彼には2つのパラメータがあります.要素を格納するarrayとソート関数です.ソート関数には2つのパラメータがあり、arrayでソートした最初のパラメータが2番目のパラメータの前にある場合は、ソート関数はtrueを返さなければなりません.ソート関数が指定されていない場合、sortはデフォルトのオペレータより小さいオペレータを使用して比較します.
一般的なエラーは、テーブルの下付きフィールドをソートしようとすることです.1つのテーブルでは、すべての下付き文字が1つの集合を構成しますが、無秩序です.彼らをソートしたい場合は、arrayにコピーしてこのarrayをソートする必要があります.例を見て、上記のソースファイルを読み取り、ソースファイルの各関数が定義されている場所の行番号を示すテーブルを作成したと仮定します.
これらの関数名をアルファベット順で印刷したい場合は、pairsを使用してこのテーブルを巡回すると、関数名が表示される順序はランダムになります.しかし、これらの名前はテーブルのkeyであるため、直接ソートすることはできません.これらの関数名を配列内に配置すると、この配列をソートできます.まず、これらの関数名を保存する配列を作成し、ソートして結果を印刷する必要があります.
注意,Luaにとって配列も無秩序である.しかし、カウントする方法を知っているので、ソートされた下付きアクセス配列を使用すれば、ソートされた関数名を得ることができます.これがpairsではなくipairsを使用して配列を巡る理由です.前者はkeyの順1,2,…,後者の表の自然記憶順を用いる.
より良い解決策があり、key値に基づいてこのテーブルを遍歴する反復子を書くことができます.オプションのパラメータfは、ソート方法を指定することができる.まず、ソートされたkeysを配列内に配置し、この配列を巡り、元のテーブルからkeyとvalueを返します.
この関数があれば、これらの関数名をアルファベット順に印刷しやすく、ループします.
印刷結果:
tableライブラリは、tableを操作するいくつかの補助関数から構成されています.彼の主な役割の一つはLuaにおけるarrayの大きさに対して合理的な解釈を与えることである.またlistから削除要素を挿入する関数やarray要素をソートする関数もいくつか用意されています.
18.1配列サイズ
Luaではarrayが最後の非nil要素で終わるとよく仮定している.この伝統的な約束には弊害がある:私たちのarrayにはnil要素を持つことができない.ほとんどのアプリケーションにとって、この制限は問題ではありません.例えば、すべてのarrayに国定的なタイプがある場合です.しかし、arrayはnil要素を持つ必要がある場合があります.この場合、arrayの大きさを明確に示す方法が必要です.
Tableライブラリは、2つの関数がarrayを操作するサイズを定義します.getnは、arrayのサイズを返します.setn、arrayのサイズを設定します.前述したように、この2つの方法はtableの1つの属性に関連しています.tableの1つのドメインにこの属性を保存するか、独立した(weak)tableを使用してtableとこの属性を関連付けます.2つの方法にはそれぞれメリットとデメリットがあるので、tableライブラリではこの2つの方法を使用しています.
通常、tableを呼び出す.setn(t,n)は、tとnを内部(weak)tableに関連付けるtableを呼び出す.getn(t)は、内部tableとtに関連付けられた値を得る.しかしながら、テーブルtに数値nを有するドメインがある場合、setnはこの値を変更し、getnはこの値を返す.Getn関数には、上記の方法でarrayのサイズを返すことができない場合、最初のnil要素が見つかるまでarrayを巡回する元の方法があります.そのため、arrayでtableをずっと使用することができます.getn(t)は正しい結果を得た.例を見てみましょう.
print(table.getn{10,2,4}) -->3
print(table.getn{10,2,nil}) -->2
print(table.getn{10,2,nil; n=3}) -->3
print(table.getn{n=1000}) -->1000
a = {}
print(table.getn(a)) -->0
table.setn(a, 10000)
print(table.getn(a)) -->10000
a ={n=10}
print(table.getn(a)) -->10
table.setn(a, 10000)
print(table.getn(a)) --> 10000
デフォルトでは、setnとgetnは内部テーブルストレージテーブルのサイズを使用します.これはarrayを汚染する余分な元素を使用しないため、最もきれいな選択です.しかしながら、nドメインを使用する方法にもいくつかの利点がある.可変パラメータを持つ関数種では、Luaカーネルはこの方法を使用してarg配列のサイズを設定します.カーネルはライブラリに依存しないため、setnを使用できません.もう1つの利点は、arrayが作成されたときに、上記の例で見たように、彼のサイズを直接初期化できることです.
setnとgetnを使用してarrayのサイズを操作するのは、ドメインnにサイズがあることを知っていても良い習慣です.tableライブラリのすべての関数(sort、concat、insertなど)はこの習慣に従います.実際には、setnを提供してドメインnの値を変更するのは、古いluaバージョンと互換性を持つためであり、この特性は将来のバージョンで変更される可能性があります.安全のため、この特性に依存すると仮定しないでください.getnを使用して配列サイズを取得し、setnを使用して配列サイズを設定してください.
18.2挿入/削除
tableライブラリはlistの任意の場所から要素を挿入および削除する関数を提供します.table.Insert関数はarray指定の位置に要素を挿入し、後ろの他のすべての要素を後ろに移動します.また、insertはarrayのサイズを変更します.例えば、aが配列{10,20,30}である場合、tableが呼び出される.Insert(a,1,15)後,aは{15,10,20,30}となる.よく使用される特殊な場合は、位置パラメータを持たずにinsertを呼び出すと、arrayの最後の位置に要素が挿入されます(したがって、要素の移動は必要ありません).次のコードは、プログラムに行ごとに独立し、すべての行をarrayに保存します.
a = {}
for line in io.lines() do
table.insert(a, line)
end
print(table.getn(a)) --> (number of linesread)
table.remove関数は、配列内の指定された位置の要素を削除し、この要素を返します.その後の要素はすべて前に移動し、配列のサイズが変わります.位置パラメータ呼び出しがない場合、arrayの最後の要素を削除します.
この2つの関数を使用すると、枝、キュー、両端キューが容易に実現されます.構造をa={}に初期化できます.1つのpush操作はtableに等しい.insert(a,x);1つのpop操作はtableに等しい.remove(a).構造の他端に要素を挿入するにはtableを使用します.insert(a,1,x);削除要素用table.remove(a,1).最後の2つの操作は、要素を往復移動しなければならないため、特に有効ではありません.しかしながら,tableライブラリのこれらの関数はC実装を用いるため,小さな配列(数百要素)にとって効率に問題はない.
18.3ソート
もう一つの役に立つ関数はtableです.sort.彼には2つのパラメータがあります.要素を格納するarrayとソート関数です.ソート関数には2つのパラメータがあり、arrayでソートした最初のパラメータが2番目のパラメータの前にある場合は、ソート関数はtrueを返さなければなりません.ソート関数が指定されていない場合、sortはデフォルトのオペレータより小さいオペレータを使用して比較します.
一般的なエラーは、テーブルの下付きフィールドをソートしようとすることです.1つのテーブルでは、すべての下付き文字が1つの集合を構成しますが、無秩序です.彼らをソートしたい場合は、arrayにコピーしてこのarrayをソートする必要があります.例を見て、上記のソースファイルを読み取り、ソースファイルの各関数が定義されている場所の行番号を示すテーブルを作成したと仮定します.
lines = {
luaH_set = 10,
luaH_get = 24,
luaH_present = 48,
}
これらの関数名をアルファベット順で印刷したい場合は、pairsを使用してこのテーブルを巡回すると、関数名が表示される順序はランダムになります.しかし、これらの名前はテーブルのkeyであるため、直接ソートすることはできません.これらの関数名を配列内に配置すると、この配列をソートできます.まず、これらの関数名を保存する配列を作成し、ソートして結果を印刷する必要があります.
a = {}
for n in pairs(lines) do table.insert(a, n) end
table.sort(a)
for i,n in ipairs(a) do print(n) end
注意,Luaにとって配列も無秩序である.しかし、カウントする方法を知っているので、ソートされた下付きアクセス配列を使用すれば、ソートされた関数名を得ることができます.これがpairsではなくipairsを使用して配列を巡る理由です.前者はkeyの順1,2,…,後者の表の自然記憶順を用いる.
より良い解決策があり、key値に基づいてこのテーブルを遍歴する反復子を書くことができます.オプションのパラメータfは、ソート方法を指定することができる.まず、ソートされたkeysを配列内に配置し、この配列を巡り、元のテーブルからkeyとvalueを返します.
function pairsByKeys (t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function () -- iterator function
i = i + 1
if a[i] == nil then return nil
else return a[i], t[a[i]]
end
return iter
end
この関数があれば、これらの関数名をアルファベット順に印刷しやすく、ループします.
for name, line in pairsByKeys(lines) do
print(name, line)
end
印刷結果:
luaH_get 24
luaH_present 48
luaH_set 10