3

Is it possible to iterate through multiple Lua tables with the same loop?

For looping through indexed tables I can do something like this:

local t1 = {"a", "b", "c"}
local t2 = {"d", "e", "f"}

local num = #t1+#t2
for i=1, num, do
    local j
    local val
    if i <= #t1 then
        j = i
        val = t1[j]
    else
        j = i-#t1
        val = t2[j]
    end

    -- Do stuff
end

but how about key-value tables?

E.g. something like this:

local t1 = {a="a", b="b", c="c"}
local t2 = {d="d", e="e", f="f"}

for key, val in pairs(t1) or pairs(t2) do
    print(key..":  '"..val.."'")
end

should result in this:

a:  'a'
b:  'b'
c:  'c'
d:  'd'
e:  'e'
f:  'f'
2
  • 1
    Note: Although you didn't explicitly say you expected this, you should be aware that key-value pairs are enumerated in an indeterminate order. (Oh, and all tables are key-value tables; It's just the constructor syntax you've chosen that's different.) Commented Nov 22, 2015 at 0:13
  • Yes, thanks for pointing it out. The order isn't important in my case, I just want to get all the pairs for both tables. Commented Nov 22, 2015 at 13:54

3 Answers 3

4
function pairs(t, ...)
  local i, a, k, v = 1, {...}
  return
    function()
      repeat
        k, v = next(t, k)
        if k == nil then
          i, t = i + 1, a[i]
        end
      until k ~= nil or not t
      return k, v
    end
end

local t1 = {a="a", b="b", c="c"}
local t2 = {d="d", e="e", f="f"}

for key, val in pairs(t1, t2) do
    print(key..":  '"..val.."'")
end

Note: this implementation does not respect __pairs metamethod.

Sign up to request clarification or add additional context in comments.

Comments

1

For the given example, I think it is much more concise and clear to just wrap the loop in an outer loop that iterates the tables.

I am assuming the primary reason OP was looking for a solution other than two loops was to avoid having to write the inner logic twice. This is a good solution to that problem and only adds two lines of code:

local t1 = {a="a", b="b", c="c"}
local t2 = {d="d", e="e", f="f"}

for _, tbl in ipairs({ t1, t2 }) do
  for key, val in pairs(tbl) do
    print(key..":  '"..val.."'")
  end
end

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
-1

While it's always nice to have an iterator like Egor's, a more efficient solution would simply be

local t1 = {a="a", b="b", c="c"}
local t2 = {d="d", e="e", f="f"}

for key, val in pairs(t1) do
    print(key..": "..val)
end
for key, val in pairs(t2) do
    print(key..":  '"..val)
end

It's simple, concise, and easily understandable.

4 Comments

That is not what OP asked for. OP requested a single loop.
That's how I did it until now, but it's not that I just do a single print in the loop, there are more lines and I want to avoid copy-paste errors when I have to change something.
@816 Then I suggest you put all the code in a function, and then call the function I'm each iteration (still using two separate loops)
Yeah, that's the way to go with two loops :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.