0Pricing
Lua Academy · Lesson

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  cherry

pairs: 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)
end

Counting 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)       -- 3

Modifying 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))
end

Collecting 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 = 8080

Nested 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()
end

Filtering 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 10

Mapping 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 WORLD

pairs 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
-- z

Quick Check

Which is true about pairs() vs ipairs()?

Recap: pairs and ipairs

Summary:

  • ipairs: ordered, integer keys starting at 1, stops at nil
  • pairs: all keys, any order, never stops early
  • Use pairs for dictionaries; ipairs for 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

  1. Tables as Arrays
  2. Tables as Dictionaries
  3. Iterating Tables with pairs and ipairs
  4. Nested Tables and Structured Data
← Back to Lua Academy