pairs
pairs() is a stateless iterator for traversing Lua tables. Unlike ipairs(), it iterates over all key-value pairs including non-sequential keys, and it correctly handles nil values. Internally, pairs() uses next() to walk the table’s hash part.
Basic Usage
t = {a = 1, b = 2, c = 3}
for k, v in pairs(t) do
print(k, v)
end
-- c 3
-- b 2
-- a 1
The iteration order is not guaranteed for hash tables — Lua uses the hash bucket order, which can vary between runs.
pairs vs ipairs
| Behavior | pairs | ipairs |
|---|---|---|
| Iterates nil values | Yes | No (stops at first nil) |
| Preserves insertion order | No | Yes (sequential indices) |
| Works with non-sequential keys | Yes | No |
| Suitable for sparse arrays | No | Yes (with caution) |
-- pairs handles nil values
t = {1, nil, 3, k = "value"}
for i, v in pairs(t) do
print(i, v)
end
-- 1 1
-- 3 3
-- k value
-- ipairs stops at first nil
for i, v in ipairs(t) do
print(i, v)
end
-- 1 1
Using next Directly
Since pairs(t) is equivalent to next, t, nil, you can call next directly for more control:
-- Iterate without creating an iterator variable
local k
while true do
k = next(t, k)
if k == nil then break end
print(k, t[k])
end
Iterating Sparse Tables
pairs correctly iterates sparse tables where ipairs would stop prematurely:
sparse = {}
sparse[1] = "first"
sparse[100] = "hundredth"
sparse[50] = "fiftieth"
for k, v in pairs(sparse) do
print(k, v)
end
-- 1 first
-- 50 fiftieth
-- 100 hundredth
Modifying Tables During Iteration
Be careful: modifying a table during iteration with pairs can cause elements to be skipped or visited multiple times:
t = {a = 1, b = 2, c = 3}
for k, v in pairs(t) do
t.d = v + 1 -- safe: adds new key
if k == "b" then
t[k] = nil -- unsafe: may skip or repeat keys
end
end
For safe modification, iterate over a copy of the keys:
for k, v in pairs(t) do
if some_condition then
t[k] = nil
end
end
-- Safer: collect keys first
local keys = {}
for k in pairs(t) do table.insert(keys, k) end
for _, k in ipairs(keys) do
if condition then t[k] = nil end
end
Checking if a Table is Empty
A common pattern for checking if a table has any entries:
function is_empty(t)
return next(t) == nil
end
is_empty({}) -- true
is_empty({a = 1}) -- false
Common Patterns
Iterating Keys Only
for k in pairs(t) do
print(k)
end
Iterating Values Only
for _, v in pairs(t) do
print(v)
end
Deep Copy
function deep_copy(obj)
if type(obj) ~= "table" then return obj end
local copy = {}
for k, v in pairs(obj) do
copy[deep_copy(k)] = deep_copy(v)
end
return copy
end
See Also
- /reference/core-functions/ref-error/ — raise errors explicitly
- /reference/core-functions/ref-pcall/ — protected call that catches errors
- /reference/core-functions/ref-select/ — select elements from a vararg list
- /tutorials/error-handling-basics/ — error handling patterns in Lua