5-3 配列の変更

プレーヤーの持ち物からアイテムを削除するなど、配列の内容を変更したいことが良くあります。Lua 言語には、これを簡単にするために、配列を操作する関数があらかじめ組み込まれています。

ここでは、配列の中から値を検索したり、新たな値を追加したり削除する方法を学びます。

ここで紹介する配列を操作する関数はごく一部です。よく多くの関数を調べたい場合は、テーブル APIのページをご覧ください。

配列への値の追加

配列に新しい値を追加するには、table.insert(array, value) を使用します。2つ目のパラメーターは、文字列、数値、または Player や IntValue などの様々なオブジェクトを指定することができます。

プレーヤーのアイテムを配列に格納していくプログラムを作成してみます。

  1. layerItemsという名前の空の配列を作成します。「local playerItems = {}」としても構いません。
playerItems = {}
  1. table.insert() と入力して、要素を配列に追加します。括弧内に、対象となる配列である playerItems を、その後に追加する要素を指定します。今回はテストとして文字列を追加したいと思います。
playerItems = {}

table.insert(playerItems, "Potion")
table.insert(playerItems, "Bread")
table.insert(playerItems, "Sleeping Bag")

print(playerItems )
  1. プロジェクトを実行します。出力ウィンドで 3 つの点 … を展開すると、playerItems の内容が表示されます。

配列からの値の削除

使用したらなくなるようなアイテムは、配列から要素を削除しなくてはなりません。値を削除するには、table.remove() を使用します。指定したパラメータに応じて、配列の最後の要素を削除するか、特定のインデックスのものを削除するのかを決定できます。

最後の値を削除する

配列の要素を削除する場合は table.remove() を使用します。また、最後の要素を削除するのであれば、パラメータに対象となる配列を渡すだけで完了です。

  1. 配列の最後の要素は「Sleeping Bag」です。これを削除するには  table.remove(playerItems) とします。
playerItems = {}

table.insert(playerItems, "Potion")
table.insert(playerItems, "Bread")
table.insert(playerItems, "Sleeping bag")

table.remove(playerItems)

print(playerItems )
  1. プロジェクトを実行します。出力ウィンドウで確認してみると、最後の値「Sleeping Bag」は表示されないのが分かると思います。

インデックスを指定しての削除

配列内の特定の位置にある要素を削除するには、2つ目のパラメータに、削除するインデックス番号を指定します。

  1. 配列1番目の「Potion」を削除してみましょう。table.remove(playerItems, 1) と入力します。
playerItems = {}

table.insert(playerItems, "Potion")
table.insert(playerItems, "Bread")
table.insert(playerItems, "Sleeping bag")

table.remove(playerItems, 1)

print(playerItems )
table.remove()の 2番目のパラメーターは、インデックス値を指定します。「Potion」などと要素を指定するとエラーになります。
  1. プロジェクトを実行します。最初の値「Potion」が削除されていることを確認します。
配列から値を削除すると、配列のサイズが変更され、削除された後にインデックス値がシフトダウンされます。「Bread」はインデックス1 になり、「Sleeping bag」はインデックス2になります。

配列内の値の検索

配列内の要素を検索する関数もあります。table.find(playerItems, “Bread”) とすると、見つかった場合はそのインデックス番号が返り、見つからなかった場合は nil が返ります。

値を見つける

  1. table.insert() で要素を追加していっても構いませんが、今回は下記のように事前に値を設定しておきます。
local playerItems = {
    "Potion",
    "Bread",
    "Sleeping Bag"
}
  1. table.find() 関数を使用して検索してみます。1つ目のパラメータは配列を、2 つ目のパラメータは検索したい値を指定します。返ってきた値を表示してみます。
local playerItems = {
    "Potion",
    "Bread",
    "Sleeping Bag"
}

local index = table.find(playerItems, "Bread")
print(index)

仮に、table.find() 関数を自作した場合は、下記のようなプログラムになるでしょう。

local function find(whichArray, itemName)
    for currentIndex = 1, #whichArray do
        if whichArray[currentIndex] == itemName then
            return currentIndex
        end
    end
    return nil
end

local index = find(playerItems, "Bread")
print(index)

値の削除

table.remove() 関数は、指定したインデックスの削除はできましたが、値を見つけてそれを削除することはできません。下記のようなプログラムを作成することで簡単に実現できます。

  1. table.find() で値を検索し、見つかったら、 table.remove() を使って削除すれば完成です。
local index = table.find(playerItems, "Bread")
if index then
    table.remove(playerItems, index)
end
  1. 以下のコードを使用して、Breadが削除されたかどうかを確認してみましょう。
for index = 1, #playerItems do
    local itemString = playerItems[index]
    print("Index " .. index .. ": " .. itemString)
end

特定の値をすべて見つけて削除する

もし「Bread」というアイテムが複数あって、それをすべて削除したい場合はどうでしょうか。table.find() と table.remove()、while ループ、if 文を使えば簡単に実現できると思いますが、ここでは for ループを使った方法でやってみましょう。

  1. 前準備として、重複するアイテムを持つ配列を用意します。
local playerItems = {
    "Potion",
    "Bread",
    "Bread",
    "Sleeping Bag"
 }
  1. 「for index = 1, #playerItems」としたい所なのですが、ちょっと待ってください。アイテムを削除すると、配列がシフトされます。それを考えた場合、インデックス1からではなく、最後のインデックスから始めた方がベストでしょう。
    #playerItemsで始まり、1 で終わるという for を作成します。もちろん、インデックス値は減らしていきます。つまり、逆方向に進む for ループを作成するのです。
for index = #playerItems, 1, -1 do

end
仮に"Bread"の削除をインデックス1から始めるとこうなります。まず、index=1で"Postion"は"Bread"でないのでスキップ。index=2は"Bread"なので削除。削除すると2番目の"Bread"("Sleeping Bag"の前のもの)がインデックス2に変わります。しかし自動的に、index=3になりますので、現在の"Sleeping Bag"が参照され、"Bread"が残ってしまうことになります。
  1. ループ内で if ステートメントを使用して、playerItems[index]内の値が”Bread”と等しいかどうかを確認し、等しい場合はアイテムを削除します。
for index = #playerItems, 1, -1 do
    if playerItems[index] == "Bread" then
        table.remove(playerItems, index)
    end
end
  1. 以下のコードを使用して、2つのBreadが削除されたかどうかを確認してみましょう。
for index = 1, #playerItems do
    local itemString = playerItems[index]
    print("Index " .. index .. ": " .. itemString)
end
  1. スクリプトを実行し、「Bread」という名前の値がすべて削除されていることを確認します。

まとめ

値を配列に削除したり、配列に追加したりすることはできますが、その際にインデックスがシフトすることに注意してください。ループを使用してテーブルを反復処理し、値のすべてのインスタンスを削除するか、最初に見つかったインスタンスのみを削除します。
キーワードreturn を使用すると、ループを停止し、必要に応じて情報を送り返すことができます。

コメントを残す