Syntax Cache
BlogMethodFeaturesHow It WorksBuild a Game
  1. Home
  2. Cheat Sheets
  3. GDScript
  4. GDScript Arrays & Dictionaries Cheat Sheet
GDScriptCheat Sheet

GDScript Arrays & Dictionaries Cheat Sheet

Quick-reference for Godot 4 collections. Each section includes copy-ready snippets with inline output comments for inventory, enemy tracking, and game state storage.

On this page
  1. 1Array Basics
  2. 2Adding and Removing Elements
  3. 3Searching and Checking
  4. 4Slicing and Duplicating
  5. 5Sorting and Filtering
  6. 6Typed Arrays
  7. 7Dictionary Basics
  8. 8Dictionary Iteration
  9. 9Dictionary Operations
  10. 10PackedArrays
  11. 11Common Collection Pitfalls
Array BasicsAdding and Removing ElementsSearching and CheckingSlicing and DuplicatingSorting and FilteringTyped ArraysDictionary BasicsDictionary IterationDictionary OperationsPackedArraysCommon Collection Pitfalls

Array Basics

GDScript arrays are dynamic, ordered, and can hold mixed types (unless typed).

Create and access
var inventory := ["sword", "shield", "potion"]
inventory[0]           # => "sword"
inventory[-1]          # => "potion" (last element)
inventory.size()       # => 3
Empty array and initialization
var enemies := []                  # empty untyped
var scores: Array[int] = []        # empty typed
var grid := [[0, 0], [0, 0]]      # 2D array
Check if empty
var loot := []
loot.is_empty()   # => true
# Or use shorthand:
if not loot:
    print("No loot found")

Adding and Removing Elements

Modify arrays with append, push, pop, insert, and erase.

append() and push_back()
var bag := ["potion"]
bag.append("key")          # => ["potion", "key"]
bag.push_back("arrow")     # => ["potion", "key", "arrow"]
bag.push_front("shield")   # => ["shield", "potion", "key", "arrow"]
insert() at index
var queue := ["goblin", "dragon"]
queue.insert(1, "skeleton")
# queue => ["goblin", "skeleton", "dragon"]
pop_back() and pop_front()
var stack := ["A", "B", "C"]
var last := stack.pop_back()    # last => "C", stack => ["A", "B"]
var first := stack.pop_front()  # first => "A", stack => ["B"]
erase() by value and remove_at() by index
var items := ["sword", "bow", "sword", "potion"]
items.erase("sword")        # removes FIRST "sword"
# items => ["bow", "sword", "potion"]

items.remove_at(0)          # removes index 0
# items => ["sword", "potion"]

Searching and Checking

Find elements, check membership, and count occurrences.

has() and find()
var inventory := ["sword", "potion", "key"]
inventory.has("potion")    # => true
inventory.has("axe")       # => false
inventory.find("key")      # => 2 (index)
inventory.find("axe")      # => -1 (not found)
count() occurrences
var loot := ["gold", "gold", "gem", "gold"]
loot.count("gold")   # => 3
loot.count("gem")    # => 1
rfind() — search from the right
var log := ["hit", "miss", "hit", "crit"]
log.rfind("hit")   # => 2  (last occurrence)

Slicing and Duplicating

Extract portions of arrays and create independent copies.

slice()
var all_enemies := ["A", "B", "C", "D", "E"]
var first_three := all_enemies.slice(0, 3)
# first_three => ["A", "B", "C"]

var last_two := all_enemies.slice(-2)
# last_two => ["D", "E"]
duplicate() — shallow vs deep
var original := [1, 2, [3, 4]]
var shallow := original.duplicate()        # nested arrays still shared
var deep := original.duplicate(true)       # fully independent copy
pick_random()
var spawn_points := [Vector2(100, 100), Vector2(500, 200), Vector2(300, 400)]
var pos := spawn_points.pick_random()
# pos => one random spawn point

Sorting and Filtering

Sort arrays in place and filter with custom callables.

sort() — default ascending
var scores := [50, 10, 90, 30]
scores.sort()
# scores => [10, 30, 50, 90]
sort_custom() — custom comparator
# Sort enemies by distance to player
var enemies: Array[Node2D] = get_tree().get_nodes_in_group("enemies")
enemies.sort_custom(func(a, b):
    return a.global_position.distance_squared_to(player_pos) < \
           b.global_position.distance_squared_to(player_pos)
)
# enemies[0] is now the closest
filter() and map()
var items := [
    {"name": "sword", "damage": 10},
    {"name": "bow", "damage": 7},
    {"name": "staff", "damage": 15},
]

# Filter: keep only items with damage > 8
var strong := items.filter(func(item): return item.damage > 8)
# strong => [{"name": "sword", ...}, {"name": "staff", ...}]

# Map: extract just the names
var names := items.map(func(item): return item.name)
# names => ["sword", "bow", "staff"]

Typed Arrays

Typed arrays enforce element types at runtime. Use them for type safety and Inspector integration.

Declare typed arrays
var hp_values: Array[int] = [100, 80, 120]
var enemy_names: Array[String] = ["Goblin", "Skeleton"]
var waypoints: Array[Vector2] = [Vector2.ZERO, Vector2(100, 50)]
Typed arrays with custom classes
var enemies: Array[Enemy] = []

func register_enemy(e: Enemy) -> void:
    enemies.append(e)  # type-checked at runtime

# This would error at runtime:
# enemies.append("not an enemy")
@export typed arrays in Inspector
@export var patrol_points: Array[Vector2] = []
@export var loot_table: Array[ItemData] = []
@export var wave_configs: Array[WaveConfig] = []
# Inspector shows type-specific UI for each element

Typed arrays show proper editors in the Inspector — Vector2 fields, Resource pickers, etc.

Dictionary Basics

Dictionaries are key-value maps. Keys can be any type (usually String or int).

Create and access
var player := {
    "name": "Hero",
    "hp": 100,
    "position": Vector2(50, 50),
}
player["name"]        # => "Hero"
player["hp"]          # => 100
player.get("mana", 0) # => 0  (default if key missing)
Add and update entries
var stats := {}
stats["strength"] = 10
stats["defense"] = 5
stats["strength"] += 2   # => 12
Check for keys
var inventory := {"sword": 1, "potion": 3}
inventory.has("sword")    # => true
inventory.has("axe")      # => false

# Safe access with get()
var count := inventory.get("axe", 0)  # => 0 (default)

Dictionary Iteration

Loop over keys, values, or both using keys(), values(), or direct iteration.

Iterate over keys (default)
var scores := {"player_1": 100, "player_2": 85, "player_3": 92}

for player_name in scores:
    print("%s: %d" % [player_name, scores[player_name]])
# player_1: 100
# player_2: 85
# player_3: 92
keys() and values()
var gear := {"weapon": "sword", "armor": "chain", "ring": "gold"}
gear.keys()     # => ["weapon", "armor", "ring"]
gear.values()   # => ["sword", "chain", "gold"]
Iterate with key-value pairs
var enemy_hp := {"goblin": 30, "skeleton": 50, "dragon": 200}

for enemy in enemy_hp:
    var hp := enemy_hp[enemy]
    if hp > 100:
        print("%s is a boss!" % enemy)  # => "dragon is a boss!"

Dictionary Operations

Merge, erase, duplicate, and compare dictionaries.

merge() — combine dictionaries
var base_stats := {"hp": 100, "atk": 10, "def": 5}
var bonus := {"atk": 3, "speed": 2}

base_stats.merge(bonus)
# base_stats => {"hp": 100, "atk": 10, "def": 5, "speed": 2}
# Note: existing keys are NOT overwritten by default

base_stats.merge(bonus, true)  # true = overwrite existing
# base_stats => {"hp": 100, "atk": 3, "def": 5, "speed": 2}
erase() — remove a key
var inventory := {"sword": 1, "potion": 3, "key": 1}
inventory.erase("key")
# inventory => {"sword": 1, "potion": 3}
duplicate()
var original := {"items": ["sword", "bow"], "gold": 100}
var copy := original.duplicate()      # shallow copy
var deep := original.duplicate(true)  # deep copy (nested arrays too)

PackedArrays

PackedArrays store a single type contiguously in memory. Much faster than generic Array for large datasets.

Common PackedArray types
var positions := PackedVector2Array()
var colors := PackedColorArray()
var ids := PackedInt32Array()
var names := PackedStringArray()
var mesh_data := PackedFloat32Array()
Build from regular array
var points := PackedVector2Array([
    Vector2(0, 0),
    Vector2(100, 0),
    Vector2(100, 100),
    Vector2(0, 100),
])

# Use for draw_polygon, collision shapes, etc.
draw_polygon(points, PackedColorArray([Color.RED]))
Append and access
var path := PackedVector2Array()
path.append(Vector2(0, 0))
path.append(Vector2(50, 25))
path.append(Vector2(100, 0))

path.size()   # => 3
path[1]       # => (50, 25)

PackedArrays are faster for iteration and use less memory than Array. Use them for paths, vertices, and large data sets.

Common Collection Pitfalls

Quick fixes for the most frequent array and dictionary bugs.

Modifying array during iteration
# BUG: removing elements while iterating skips items
for enemy in enemies:
    if enemy.is_dead():
        enemies.erase(enemy)  # index shifts — skips next!

# FIX: iterate a copy, or iterate backwards
for enemy in enemies.duplicate():
    if enemy.is_dead():
        enemies.erase(enemy)
Array assignment shares reference
# BUG: both point to same array
var a := [1, 2, 3]
var b = a
b.append(4)
# a => [1, 2, 3, 4]  — a was modified too!

# FIX: use duplicate()
var c := a.duplicate()
c.append(5)
# a is unchanged
Dictionary missing key crash
# BUG: accessing missing key crashes
var data := {"name": "Goblin"}
data["hp"]  # KeyError!

# FIX: use get() with default
var hp := data.get("hp", 100)  # => 100

# Or check first
if data.has("hp"):
    print(data["hp"])

Always use .get(key, default) or .has(key) when the key might not exist.

Learn GDScript in Depth
GDScript Foundations Practice →GDScript Resources Practice →
Warm-up1 / 2

Can you write this from memory?

Declare an array called upgrade_names containing the strings 'speed', 'damage', and 'health'.

See Also
Resources →Signals →

Start Practicing GDScript

Free daily exercises with spaced repetition. No credit card required.

← Back to GDScript Syntax Practice
Syntax Cache

Build syntax muscle memory with spaced repetition.

Product

  • Pricing
  • Our Method
  • Daily Practice
  • Design Patterns
  • Interview Prep

Resources

  • Blog
  • Compare
  • Cheat Sheets
  • Vibe Coding
  • Muscle Memory

Languages

  • Python
  • JavaScript
  • TypeScript
  • Rust
  • SQL
  • GDScript

Legal

  • Terms
  • Privacy
  • Contact

© 2026 Syntax Cache

Cancel anytime in 2 clicks. Keep access until the end of your billing period.

No refunds for partial billing periods.