How to iterate through table in Lua?

174,068

Solution 1

To iterate over all the key-value pairs in a table you can use pairs:

for k, v in pairs(arr) do
  print(k, v[1], v[2], v[3])
end

outputs:

pears   2   p   green
apples  0   a   red
oranges 1   o   orange

Edit: Note that Lua doesn't guarantee any iteration order for the associative part of the table. If you want to access the items in a specific order, retrieve the keys from arr and sort it. Then access arr through the sorted keys:

local ordered_keys = {}

for k in pairs(arr) do
    table.insert(ordered_keys, k)
end

table.sort(ordered_keys)
for i = 1, #ordered_keys do
    local k, v = ordered_keys[i], arr[ ordered_keys[i] ]
    print(k, v[1], v[2], v[3])
end

outputs:

  apples  a   red     5
  oranges o   orange  12
  pears   p   green   7

Solution 2

If you want to refer to a nested table by multiple keys you can just assign them to separate keys. The tables are not duplicated, and still reference the same values.

arr = {}
apples = {'a', "red", 5 }
arr.apples = apples
arr[1] = apples

This code block lets you iterate through all the key-value pairs in a table (http://lua-users.org/wiki/TablesTutorial):

for k,v in pairs(t) do
 print(k,v)
end

Solution 3

For those wondering why ipairs doesn't print all the values of the table all the time, here's why (I would comment this, but I don't have enough good boy points).

The function ipairs only works on tables which have an element with the key 1. If there is an element with the key 1, ipairs will try to go as far as it can in a sequential order, 1 -> 2 -> 3 -> 4 etc until it cant find an element with a key that is the next in the sequence. The order of the elements does not matter.

Tables that do not meet those requirements will not work with ipairs, use pairs instead.

Examples:

ipairsCompatable = {"AAA", "BBB", "CCC"}
ipairsCompatable2 = {[1] = "DDD", [2] = "EEE", [3] = "FFF"}
ipairsCompatable3 = {[3] = "work", [2] = "does", [1] = "this"}

notIpairsCompatable = {[2] = "this", [3] = "does", [4] = "not"}
notIpairsCompatable2 = {[2] = "this", [5] = "doesn't", [24] = "either"}

ipairs will go as far as it can with it's iterations but won't iterate over any other element in the table.

kindofIpairsCompatable = {[2] = 2, ["cool"] = "bro", [1] = 1, [3] = 3, [5] = 5 }

When printing these tables, these are the outputs. I've also included pairs outputs for comparison.

ipairs + ipairsCompatable
1       AAA
2       BBB
3       CCC

ipairs + ipairsCompatable2
1       DDD
2       EEE
3       FFF

ipairs + ipairsCompatable3
1       this
2       does
3       work

ipairs + notIpairsCompatable

pairs + notIpairsCompatable
2       this
3       does
4       not

ipairs + notIpairsCompatable2

pairs + notIpairsCompatable2
2       this
5       doesnt
24      either

ipairs + kindofIpairsCompatable
1       1
2       2
3       3

pairs + kindofIpairsCompatable
1       1
2       2
3       3
5       5
cool    bro

Solution 4

All the answers here suggest to use ipairs but beware, it does not work all the time.

t = {[2] = 44, [4]=77, [6]=88}

--This for loop prints the table
for key,value in next,t,nil do 
  print(key,value) 
end

--This one does not print the table
for key,value in ipairs(t) do 
  print(key,value) 
end
Share:
174,068
Lemony Lime
Author by

Lemony Lime

Updated on July 05, 2022

Comments

  • Lemony Lime
    Lemony Lime almost 2 years

    So, I have a table something along these lines:

    arr =
    {
      apples = { 'a', "red", 5 },
      oranges = { 'o', "orange", 12 },
      pears = { 'p', "green", 7 }
    }
    

    It doesn't seem like it's possible to access them based on their index, and the values themselves are tables, so I just made the first value of the nested table the index of it, so it now looks like this:

    arr =
    {
      apples = { 0, 'a', "red", 5 },
      oranges = { 1, 'o', "orange", 12 },
      pears = { 2, 'p', "green", 7 }
    }
    

    So, now any time I use one of these tables, I know what the index is, but still can't get to the table using the index, so I started to write a function that loops through them all, and check the indexes until it finds the right one. Then I realized... how can I loop through them if I can't already refer to them by their index? So, now I'm stuck. I really want to be able to type arr.apples vs arr[1] most of the time, but of course it's necessary to do both at times.

    • Kjell Hedström
      Kjell Hedström over 8 years
      This with answer from @greatwolf will fail unless there is an "," between each array-row. arr = { apples = { 0, 'a', "red", 5 }, oranges = { 1, 'o', "orange", 12 }, pears = { 2, 'p', "green", 7 }, } a working example can be seen at: ideone.com/yWKHx7
    • greatwolf
      greatwolf over 8 years
      @KjellHedström I've edited the OP's question and fixed up the minor syntax errors. good catch.
  • Lemony Lime
    Lemony Lime almost 11 years
    Just noticed... why does it print them in the wrong order? If it printed them in order, I could leave out the index variable in the table, and just rely on the order that it prints to find the index, which would be nice.
  • greatwolf
    greatwolf almost 11 years
    Lua doesn't guarantee the iteration order for the associative part of the table.
  • greatwolf
    greatwolf almost 11 years
    @Lemony I've added an example on how you can traverse the table in a particular order.
  • Henrik Erlandsson
    Henrik Erlandsson about 10 years
    And if you want them in the #$%^& order they come in the JSON file!? Bah.
  • beatgammit
    beatgammit almost 10 years
    @HenrikErlandsson - A JSON object is unordered. See the spec.
  • Ray Toal
    Ray Toal over 9 years
    When Crockford writes "An object is an unordered set of name/value pairs" he means a JSON string represents an object with pairs whose order should not be relied upon. However JSON is a text interchange format, and what people call a "JSON object" is really just a string, so yes, it pairs are ordered. I think the term "JSON object" is overused, personally. Henrik is correct that the idea of someone wanting to iterate in the order given in the JSON string is a valid one, but a "wrong" one indeed!
  • Kjell Hedström
    Kjell Hedström over 8 years
    What version of Lua does this work with? On ideone.com this code will fail ideone.com/CeRqu9, using Luac 5.2
  • Kjell Hedström
    Kjell Hedström over 8 years
    OK, the code given in the question was not correct. Between each entry-array there must be a ","
  • mlepage
    mlepage about 6 years
    @lemony-lime It's correct the order of the associative part is unspecified. The reason, is typically because it is implemented using a "hash table" which is inherently unordered (because the keys are hashed from the values by an arbitrary computation), but it could also be because it's some kind of tree storage with ordering that is allowed to change to give good performance (for insertions and deletions).
  • Zeruno
    Zeruno over 4 years
    Why does it not print all the time?
  • sgowd
    sgowd over 4 years
    I am beginner at Lua. I don't know. But I encountered this issue while testing my code.
  • Seniru Pasan
    Seniru Pasan about 4 years
    @sgowd why are you adding ',nil' after the table 't' - it's not required. Also the issue mentioned by you (actually not an issue) is that ipairs returns a set of integer based keys. That means if your table has string-based keys, using ipairs you are converting them to integer keys. The docs describes the difference very clearly.
  • sgowd
    sgowd about 4 years
    @SeniruPasan Thanks for the tip on not adding the ',nil'; I will try it out. In the example I have given, the keys are integer based keys. Baggef's answer stackoverflow.com/a/60088452/1566608 gives more clarity on why ipairs doesn't work all the time.