Lua - Chaining Iterator
Lua is not having built-in support for chaining iterators. But we can create our own chaining iterator by table manipulations. Goal of this chain iterator is to iterate multiple iterables sequentially as they are single iterable. In this chapter, we'll discuss various options to create a chaining iterator with examples.
Example - Create a Custom Chaining Iterator
We're creating a function which can take multiple iterables represented by tables and it will return a single iterator which iterates through each iterables one by one and we'll print each values.
main.lua
-- function representing chain iterator
function chainIterator(...)
local iterables = {...}
local iterable_index = 1
local index = 1
return function()
while iterable_index <= #iterables do
local iterable = iterables[iterable_index]
if type(iterable) ~= "table" then -- if argument is not a table
error("Invalid input. Only table can be passed.")
end
-- iterate through table entries
if index <= #iterable then
local value = iterable[index]
index = index + 1
return value
else -- go to next table
iterable_index = iterable_index + 1
index = 1 -- Reset index for the next table
end
end
return -- end of iteration
end
end
local list1 = {1, 2, 3, 4}
local list2 = {'a', 'b', 'c'}
local list3 = {10, 20}
for item in chainIterator(list1, list2, list3) do
print(item)
end
Output
When the above code is built and executed, it produces the following result −
1 2 3 4 a b c 10 20
Explanation
chainIterator(...) function takes variable arguments as tables and stored in itearable table.
iterable_index is to track current table and index is to track current item of a table.
Using return function() we've returned an anonymous function which acts as an iterator to give the next item.
while iterable_index <= #iterables do loop is to iterate all tables.
if index <= #iterable then is used to return item of current iterable. Once current iterable is done, we're moving to next iterable.
Example - Chaining into a New Table
Instead of creating a chaining iterator, we can combine tables as well as shown in example below −
main.lua
function combineTables(...)
local result = {}
-- iterate through each table
for i = 1, select('#', ...) do
-- get the iterator
local iterable = select(i, ...)
if type(iterable) ~= "table" then
error("Invalid input. Only table can be passed.")
end
-- iterate through table values and insert into result table
for _, value in ipairs(iterable) do
table.insert(result, value)
end
end
-- return the combined table
return result
end
local list1 = {1, 2, 3, 4}
local list2 = {'a', 'b', 'c'}
local list3 = {10, 20}
local combinedList = combineTables(list1, list2, list3)
for _,item in ipairs(combinedList) do
print(item)
end
Output
When the above code is built and executed, it produces the following result −
1 2 3 4 a b c 10 20
Explanation
combineTables(...) function takes variable arguments as tables and returns a combined table of all values of the table passed.
result represents the combined table. Using for loop, we're navigating through each table.
Using ipairs, we're iterating each element of the input table and values are inserted to combined table as result.
Finally result is returned.