Iterating Tables with pairs and ipairs
Traverse tables safely using pairs() and ipairs().
Iterating Tables with pairs and ipairs is a free Lua Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Lua Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
ipairs: Ordered Array Iteration
ipairs(t) iterates over the integer sequence starting at index 1, yielding (index, value) pairs. It stops at the first nil. This is the safe, predictable choice for array-like tables where order matters.
local fruits = {"apple","banana","cherry"}
for i, fruit in ipairs(fruits) do
print(i, fruit)
end
-- 1 apple
-- 2 banana
-- 3 cherrypairs: All Keys
pairs(t) iterates over every non-nil key-value pair in the table, in unspecified order. It uses the next() function internally. Use pairs for dictionaries, mixed tables, or when you need to visit all keys regardless of type.
local info = {name="Lua", version=5.4, embedded=true}
for k, v in pairs(info) do
print(k, v)
end
-- name Lua
-- version 5.4
-- embedded true (order may vary)Choosing Between pairs and ipairs
Use ipairs for sequential arrays (guaranteed order, stops at nil). Use pairs for dictionaries, mixed tables, or when you need all keys. Using pairs on an array works but gives no order guarantee. Using ipairs on a dictionary misses non-integer keys.
local mixed = {10, 20, label="hello", 30}
-- ipairs: only sees 10, 20, 30 in order
for i, v in ipairs(mixed) do
io.write(v .. " ")
end
print() -- 10 20 30
-- pairs: sees everything
for k, v in pairs(mixed) do
print(k, v)
endCounting Elements
For sequences, #t gives the count. For dictionaries, #t is unreliable — iterate with pairs and count manually. This is an important distinction that prevents bugs when working with mixed or string-keyed tables.
local arr = {10, 20, 30}
print("#arr:", #arr) -- 3 (reliable)
local dict = {a=1, b=2, c=3}
print("#dict:", #dict) -- 0 (unreliable for dicts!)
local count = 0
for _ in pairs(dict) do count = count + 1 end
print("count:", count) -- 3Modifying Values During Iteration
You can safely update the value of an existing key while iterating with pairs. However, adding or removing keys during iteration has undefined behavior. Collect changes and apply them after the loop.
local prices = {apple=1.0, banana=0.5, cherry=2.0}
-- Safe: update existing values
for k, v in pairs(prices) do
prices[k] = v * 1.1 -- 10% markup
end
for k, v in pairs(prices) do
print(k, string.format("%.2f", v))
endCollecting Keys
A common operation is collecting all keys into a sorted array for deterministic output. Iterate with pairs to gather keys, then use table.sort to order them.
local config = {host="localhost", port=8080, debug=true}
local keys = {}
for k in pairs(config) do
keys[#keys+1] = k
end
table.sort(keys)
for _, k in ipairs(keys) do
print(k, "=", config[k])
end
-- debug = true
-- host = localhost
-- port = 8080Nested Table Iteration
For nested tables (table of tables), combine two loops: the outer loop iterates the top level, the inner loop iterates each nested table. This pattern handles any depth with recursion for truly arbitrary nesting.
local matrix = {
{1,2,3},
{4,5,6},
{7,8,9},
}
for i, row in ipairs(matrix) do
for j, val in ipairs(row) do
io.write(string.format("%3d", val))
end
print()
endFiltering with ipairs
Build a filtered list by iterating with ipairs and appending elements that pass a predicate. The result is a new array containing only the matching elements.
local function filter(t, pred)
local result = {}
for _, v in ipairs(t) do
if pred(v) then result[#result+1] = v end
end
return result
end
local nums = {1,2,3,4,5,6,7,8,9,10}
local evens = filter(nums, function(n) return n % 2 == 0 end)
print(table.concat(evens, " ")) -- 2 4 6 8 10Mapping with ipairs
Apply a transformation to every element: iterate and build a new array with the transformed values. This is the Lua equivalent of map() in functional languages.
local function map(t, fn)
local result = {}
for i, v in ipairs(t) do
result[i] = fn(v)
end
return result
end
local nums = {1, 2, 3, 4, 5}
local doubled = map(nums, function(n) return n * 2 end)
print(table.concat(doubled, " ")) -- 2 4 6 8 10
local words = {"hello","world"}
local upper = map(words, string.upper)
print(table.concat(upper, " ")) -- HELLO WORLDpairs on Custom Iterators
You can make a custom object iterable by returning an iterator and state from a function. The pattern mirrors how pairs works internally: it returns next, t, nil. Your iterator factory similarly returns a function plus optional state.
local function values(t)
local i = 0
return function()
i = i + 1
return t[i]
end
end
for v in values({"x","y","z"}) do
print(v)
end
-- x
-- y
-- zQuick Check
Which is true about pairs() vs ipairs()?
Recap: pairs and ipairs
Summary:
ipairs: ordered, integer keys starting at 1, stops at nilpairs: all keys, any order, never stops early- Use
pairsfor dictionaries;ipairsfor arrays - Never add/remove keys mid-pairs; update existing values is safe
- Collect+sort keys for deterministic output
Frequently asked questions
Is the “Iterating Tables with pairs and ipairs” lesson free?
Yes — the full text of “Iterating Tables with pairs and ipairs” is free to read here on the web, and the Lua Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Lua Academy course, upgrade to CoddyKit PRO.
What will I learn in “Iterating Tables with pairs and ipairs”?
Traverse tables safely using pairs() and ipairs(). You practise Lua Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Lua Academy?
No prior experience is required. Lua Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Iterating Tables with pairs and ipairs” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Lua Academy lesson?
Yes. Every Lua Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Tables as Arrays
- Tables as Dictionaries
- Iterating Tables with pairs and ipairs
- Nested Tables and Structured Data