luaguides

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

Behaviorpairsipairs
Iterates nil valuesYesNo (stops at first nil)
Preserves insertion orderNoYes (sequential indices)
Works with non-sequential keysYesNo
Suitable for sparse arraysNoYes (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