What is the difference between pairs() and ipairs() in Lua?

ipairs() and pairs() are slightly different, as you can see on the manual reference.
A less-technical description could be that:

  • ipairs() returns index-value pairs and is mostly used for numeric tables.
    The non-numeric keys are ignored as a whole, similar to numeric indices less than 1.
    In addition, gaps in between the indexes lead to halts.
    The ordering is deterministic, by numeric magnitude.

  • pairs() returns key-value pairs and is mostly used for associative tables.
    All keys are preserved, but the order is unspecified.

In addition, while pairs() may be used to get the size of a table (see this other question), using ipairs() for the same task is unsafe a priori, since it might miss some keys.

The differences between both options is illustrated in the following code fragment.

> u = {}
> u[-1] = "y"
> u[0] = "z"
> u[1] = "a"
> u[3] = "b"
> u[2] = "c"
> u[4] = "d"
> u[6] = "e"
> u["hello"] = "world"
>
> for key, value in ipairs(u) do print(key, value) end
1       a
2       c
3       b
4       d
>
> for key, value in pairs(u) do print(key, value) end
1       a
2       c
3       b
4       d
6       e
0       z
hello   world
-1      y
> 

As we can see in the example, while all keys appear in the output for pairs(), some are missing for ipairs():
hello because it is not a numeric key;
-1 and 0 since, despite they are numeric, their value is less than 1, and;
6 given that we implicitly have u[5] = nil, and finding a nil value while iterating is exactly the ending condition for ipairs().

Finally, note that as in your example, when you create a table without specifing any of the keys, e.g., a = {"one", "two", "three"}, numeric keys starting in 1 are implicitly assigned to each of the values, i.e. the definition is understood as a = { [1] = "one", [2] = "two", [3] = "three" }.
As a consequence, using pairs() or ipairs() is mostly the same in these scenarios, except for the non-guaranteed ordering of pairs().

Leave a Comment