こんにちは、ロブスタのハルです!
前回の講座ではテーブルを使ったNPCとの会話プログラムを実装しました。
今回はより深く理解するためにテーブルに対してできる操作について解説します。
前回の講座を見ていない方はこちらからご覧ください。
テーブルについて(復習)
テーブルとは複数の値をまとめるための方法です。Lua言語のテーブルは配列と連想配列という2つの要素を足し合わせたものです。配列は順番ありで複数の値を保管します。連想配列は順番なしで複数の値を保管する方法でキーとバリューのセットとなっています。
テーブルの中身のことを要素ということがあります。
要素の変更
既にあるテーブルの要素を変更するには以下のように書きます。
-- 配列モード
テーブル名[インデックス] = 値
-- 連想配列モード
テーブル名.キー = バリュー
テーブル名["キー"] = バリュー
例えば、以下のような感じです。
-- 配列モード
local t1 = {1, 3, 5}
t1[1] = 2
t1[2] = 4
t1[3] = 6
-- 連想配列モード
local t2 = {key = "value"}
t2["key"] = "newValue"
t2.key = "second"
要素の追加
テーブルに要素を追加する方法はいくつかあります。
1.末尾に追加
テーブルの末尾に要素を追加するにはinsertメソッドを使います。
具体的には以下のように書きます。
table.insert(テーブル名, 追加したい値)
local t = {}
table.insert(t, "new")
ただし、insertメソッドが使えるのは配列モードのテーブルのみです。
2.特定のインデックスに追加
特定のインデックスに追加する方法は2つあります。
1つは要素の変更と同じような形で追加する方法です。
-- 配列モード
local t = {element}
t[2] = new
-- 連想配列モード
local t2 = {a=1, b=2}
t2.c = 3
つまり、テーブルに存在しないインデックスまたはキーにバリューをセットしようとすると特定のインデックスに追加することができます。
この方法で注意するべきはすでにテーブルにインデックスまたはキーが存在する場合はその中身が書き換えられてしまうということです。
もう1つはinsertメソッドを使う方法です。ただし、これは配列モードのテーブルにしか使えません。
-- 配列モードのみ
table.insert(テーブル名, 追加したいインデックス, 追加したい値)
local t = {"abc", "ghi"}
table.insert(t, 2,"def")
print文で確認してみるとtの中身が{“abc”, “def”, “ghi”}となっていることが確認できます。
3.#で追加
これは#演算子を使う方法です。
local t = {1, 2, 3, 4, 5, 6, 7, 8}
t[#t+1] = 9
まず、#tは現在のテーブルtの要素数を表しているので8となります。
#t+1によって8+1=9番目を表すことになり、tの9番目に9を追加するという意味になります。
要素の削除
要素を削除する方法も2つあります。
1つは削除したいキーのバリューにnilを代入することです。
ただし、これは連想配列モードのテーブルにしか使えません。
local t = {a=1, b=2, c=3}
t["b"] = nil
もう1つはremoveメソッドを使うことです。
ただし、これは配列モードのテーブルにしか使えません。
table.remove(テーブル名, 削除したいインデックス)
local t = {1, 2, 3, 4, 5, 6, 7, 8}
table.remove(t, 3)
print文で確認すると3番目の要素である3がなくなり、その後ろの要素が前に押し出されていると思います。
要素の検索(取得)
第18回で紹介したようにインデックスまたはキーを使うことで要素を取得できます。
-- 配列モード
local t = {1, 2, 3, 4, 5}
print(t[2])
-- 連想配列モード
local t2 = {a=1, b=2, c=3}
value = t2.c
print(value)
テーブルの要素数を取得
第19回で紹介したように#演算子を使うことでテーブルの要素数を取得できます。ただし、#演算子は配列モードにしか使うことができません。
-- 配列モード
local t = {1, 2, 3, 4, 5}
print(#t)
連想配列モードのテーブルの要素数を取得する方法は次回解説します。
テーブルのソート
ソートとはある一定のルールに従ってデータを並び替えることです。
よく使われるものとして昇順ソートと降順ソートがあります。
昇順ソート
昇順とは小さい順のことです。例えば、1, 2, 3, 4, 5は昇順です。
昇順ソートにはsortメソッドを使います。
local t = {2, 5, 1, 9, 3, 6, 7, 4, 8, 10}
table.sort(t)
print(t)
こうすると、1, 2, 3, 4, 5, 6, 7, 8, 9, 10のようにきれいに昇順ソートされたテーブルが出力されます。
また、ソートは数値だけでなく、文字列に対しても行うことができます。
文字列の昇順ソートはa, b, c, d, eのような順番になります。
local t = {"apple", "cherry", "dragon fruit", "banana"}
table.sort(t)
print(t)
結果はapple, banana, cherry, dragon fruitの順になります。
昇順ソートは連想配列モードのテーブルにも使えます。
この場合はsortメソッドに比較関数を渡してあげる必要があります。
local people = {
{name = "Charlie", age = 35},
{name = "Alice", age = 30},
{name = "Bob", age = 25}
}
table.sort(people, function (a, b) return a.name < b.name end)
print(people)
function (a, b) return a.name < b.name endの部分が比較関数となっています。
このsortメソッドは内部でソートアルゴリズムという決まりに従って動いているのでここでは説明を省略します。
結果はぜひ自分で確かめてみてください。
降順ソート
降順は大きい順のことです。例えば、5, 4, 3, 2, 1は降順です。
降順ソートもsortメソッドを使うのですが、引数として比較関数を渡してあげる必要があります。
local t = {2, 5, 1, 9, 3, 6, 7, 4, 8, 10}
table.sort(t, function (a, b) return a > b end)
print(t)
結果は10, 9, 8, 7, 6, 5, 4, 3, 2, 1のように降順ソートされたものが出力されます。
このsortメソッドはテーブルから要素を2つずつ取り出して比較します。そのときに比較関数も呼び出されて、もし前の要素aが後の要素bよりも大きければtrueを、そうでなければfalseを返します。trueを返したとき、aがbの前に来ると判断されて並び替えが発生します。
また、文字列に対しても降順ソートを行うことができます。
local t = {"apple", "cherry", "dragon fruit", "banana"}
table.sort(t, function (a, b) return a > b end)
print(t)
出力はdragon fruit, cherry, banana, appleのようになります。
さらに連想配列モードのテーブルに対しても降順ソートを行うことができます。
local people = {
{name = "Alice", age = 30},
{name = "Bob", age = 25},
{name = "Charlie", age = 35}
}
table.sort(people, function(a, b) return a.age > b.age end)
print(people)
これは年齢ageを降順にソートしたものとなります。結果はぜひ自分で確かめてみてください。
まとめ
- 要素を変更するには取り出した要素に新しい値を代入する
- 要素を追加するはinsertメソッドまたは存在しないインデックスかキーを使うまたは#演算子を使う
- 要素を削除するにはそのキーに対してnilを代入するまたはremoveメソッドを使う
- 要素を取得するにはインデックスまたはキーを使う
- 要素数を取得するには#演算子を使う
- テーブルのソートにはsortメソッドを使う
お疲れ様でした。今回はテーブルの機能を簡単に紹介してみました。しかし、テーブルの力はループと組み合わせることによって発揮されます。
そこで次回はループとテーブルの組み合わせによる処理について解説します。
コメント