【Godot4.x】Arrayのよく使う関数まとめ

この記事では 配列を扱う Array のよく使う関数についてまとめてみました。

 

Arrayのよく使う関数まとめ

 

生成、初期化

 

生成は基本的に を使って行います。

 

Packed〜Array (例えばPackedInt32Arrayなど)というクラスも存在しているのですが、Godot4.xからArrayで扱う型を指定できるようになったので、生成は で書いて変数側に型を指定するという書き方が良さそうです。

 

# 数値配列の作成
var arr:Array[int] = [1, 2, 3, 4]

 

要素をすべて初期化するには clear() を使います。

 

# 数値配列の作成
var arr:Array[int] = [1, 2, 3, 4]
# 要素をすべて消す.
arr.clear()

 

複製

 

Arrayを複製するには duplicate() を追加います。

 

    # 数値配列の作成
    var arr1:Array[int] = [1, 2, 3, 4]
    # 複製.
    var arr2 = arr1.duplicate()
    arr2[0] = 0 # 先頭の要素を書き換えてみる.
    print("arr1: ", arr1)
    print("arr2: ", arr2)

 

結果
arr1: [1, 2, 3, 4]
arr2: [0, 2, 3, 4]

 

プログラムに慣れていないとやりがちなミスとして「アドレスコピー」と「実体の複製」を混同することです。

 

GDScriptのオブジェクトの代入は基本的にアドレスコピーなので、以下の記述だとそれぞれの変数の中身が書き換わってしまいます。(先頭の要素の値がそれぞれ "0" となります)

 

    # 数値配列の作成
    var arr1:Array[int] = [1, 2, 3, 4]
    # 複製.
    var arr2 = arr1
    arr2[0] = 0 # 先頭の要素を書き換えてみる.
    print("arr1: ", arr1)
    print("arr2: ", arr2)

 

結果
arr1: [0, 2, 3, 4]
arr2: [0, 2, 3, 4]

 

要素の追加

 

要素の追加は append() で行います。(末尾への追加)

 

    # 数値配列の作成
    var arr1:Array[int] = [1, 2, 3, 4]
    arr1.append(10)
    arr1.append(20)
    print("arr1: ", arr1)

 

結果
arr1: [1, 2, 3, 4, 10, 20]

 

先頭・末尾への追加

 

先頭への追加は push_front() 、末尾への追加は push_back() を使用します。

 

    # 数値配列の作成
    var arr1:Array[int] = [1, 2, 3, 4]
    arr1.push_front(10) # 先頭へ追加.
    arr1.push_back(20) # 末尾へ追加.
    print("arr1: ", arr1)

 

結果
arr1: [10, 1, 2, 3, 4, 20]

 

append()とpush_back() の同じ機能の関数がなぜ存在するのか?

append() と push_back() はどちらも要素を末尾へ追加する関数です。

関数が重複している原因はおそらく GDScript が参考にしているスクリプト言語 Python でのリストへの要素追加が append() となっているためだと思われます。

 

Arrayを結合する

 

別のArrayを結合する場合は append_array() を使用します。

 

    # 数値配列の作成
    var arr1:Array[int] = [10, 25, 40, 99]
    var arr2 = [1, 2, 4]
    arr1.append_array(arr2)
    print(arr1)

 

結果
[10, 25, 40, 99, 1, 2, 4]

 

要素の削除

 

要素の削除は remove_at() / erase() で行うことができます。

 

    # 数値配列の作成
    var arr1:Array[int] = [10, 25, 40, 99]
    arr1.remove_at(2) # 要素[2] (=40) を削除
    print("arr1: ", arr1)
    arr1.erase(99) # 値 99 を削除
    print("arr1: ", arr1)

 

結果
arr1: [10, 25, 99]
arr1: [10, 25]

 

remove_at() は要素番号を指定して削除し、erase() は直接値を指定して値が一致する要素を削除します。

 

要素を取り出して削除

 

pop_front() で先頭の要素を取り出して削除、pop_back() で末尾の要素を取り出して削除できます。

 

    # 数値配列の作成
    var arr1:Array[int] = [10, 25, 40, 99]
    var front = arr1.pop_front() # 先頭を取り出す.
    print("front: ", front)
    print("arr1: ", arr1)
    var back = arr1.pop_back() # 末尾を取り出す.
    print("back: ", back)
    print("arr1: ", arr1)

 

結果
front: 10
arr1: [25, 40, 99]
back: 99
arr1: [25, 40]

 

なお要素の位置を指定して取り出し+削除する場合には pop_at() を使います。

 

素数の取得

 

Arrayの要素数size() で取得できます。

 

    # 数値配列の作成
    var arr1:Array[int] = [10, 25, 40, 99]
    print(arr1.size())

 

結果
4

 

なお要素数が0かどうかを判定する場合には is_empty() という関数で行うこともできます。

 

指定の値が存在するかどうか

 

Arrayの中に指定の値があるかどうかを調べるには has() という関数がありますが、個人的には in 演算子を使うとコードを短くかけておすすめです。

 

    # 数値配列の作成
    var arr1:Array[int] = [10, 25, 40, 99]
    if 10 in arr1:
        print("arr1の中に 10 がある")
        
    if not 100 in arr1: # 否定は "not" を使う.
        print("arr1の中に 100 はない")

 

結果
arr1の中に 10 がある
arr1の中に 100 はない

 

要素の取り出し

 

要素の取り出しは通常 [] 演算子でアクセスします。

 

    # 数値配列の作成
    var arr1:Array[int] = [10, 25, 40, 99]
    var a = arr1[2]
    print("[2]の要素は ", a)

 

結果
[2]の要素は 40

 

ランダムな位置の値を取り出す

 

Arrayの中からランダムな位置にある値を取り出すには pick_random() を使用します。

 

    randomize() # 乱数を初期化
    
    var arr = [1, 5, 10, 99]
    var a = arr.pick_random()
    print("a: ", a)

 

randomize() はゲーム開始時にだけ呼び出せば問題ありません。

 

順序

 

ソートする

 

ソートとは、Arrayの値を特定の順番で並び替えることです。例えばArrayの中身が数値の場合、 sort() を使うと昇順(小さい値から大きい値)に並び替えます。

 

    # 数値配列の作成
    var arr:Array[int] = [9, 2, 7, 3, 5]
    arr.sort()
    print(arr)

 

結果
[2, 3, 5, 7, 9]

 

カスタムソート

 

数値以外の値をソートする場合、ソートルールが特殊な場合は sort_custom() を使います。

 

## キャラクター定義.
class Chara:
    var lv:int
    var str:String
    var hp:int
    func _init(_lv:int, _name:String, _hp:int) -> void:
        lv = _lv
        str = _name
        hp = _hp
    func _to_string() -> String:
        return "[%s] Lv:%s HP:%d"%[str, lv, hp]

func _ready() -> void:
    var arr:Array[Chara] = []
    arr.append(Chara.new(5, "勇者", 120))
    arr.append(Chara.new(1, "魔法使い", 30))
    arr.append(Chara.new(4, "戦士", 150))
    
    # カスタムソート (レベルで降順ソートする).
    arr.sort_custom(func(a:Chara, b:Chara): return a.lv > b.lv)
    
    print(arr)

 

結果
[[勇者] Lv:5 HP:120, [戦士] Lv:4 HP:150, [魔法使い] Lv:1 HP:30]

 

逆順にする

 

値の並びを逆にするには reverse() を使用します。

 

    var arr = [1, 5, 10, 99]
    arr.reverse()
    print(arr)

 

結果
[99, 10, 5, 1]

 

シャッフルする

 

Arrayが持っている値を不規則に入れ替える場合には shuffle() を使用します。

 

    randomize() # 乱数を初期化
    
    var arr = [1, 5, 10, 99]
    arr.shuffle()
    print(arr)

 

結果
[99, 10, 1, 5]

 

高階関数

 

高階関数とは関数を引数に受け取って、Array内の値に対して処理を行う関数です。

 

map(): すべての値に対して加工する

 

map() は Array内の値をすべて加工します。

 

    var arr = [1, 5, 10, 99]
    # すべての値を10倍する.
    arr = arr.map(func(a): return a * 10)
    print(arr)

 

結果
[10, 50, 100, 990]

 

filter(): 指定の条件に一致した値だけにフィルタリングする

 

filter() は bool を返すラムダ式を渡して、trueとなるものだけにフィルタリングする関数です。

 

    var arr = [1, 5, 10, 99, 100]
    # 奇数の値のみ取り出す.
    arr = arr.filter(func(a): return a % 2 == 1)
    print(arr)

 

結果
[1, 5, 99]