Lua - Iterating over Lists
In order to iterate a list, it is good practice to build an iterator which can return the next element of the list. See the following code of the iterator function on the list.
-- iterate through the list
local function iterate(self, current)
-- if current is nil
-- set the current as first node
if not current then
current = self.first
-- if current is present
-- set current as current next
elseif current then
current = current._next
end
-- return current
return current
end
-- return the iterator
function list:iterate()
return iterate, self, nil
end
We can use list:iterate() function to iterate the list which will return the next element when invoked in a for loop.
We'll build the list and then add method to insert an element. Finally, using iterate function in a for loop, we'll iterate the list.
Step 1: Create List
Create a List with a push method to add an element to the end of the list.
-- List Implementation
list = {}
list.__index = list
-- push an element to the end of the list
function list:push(t)
-- move till last node
if self.last then
self.last._next = t
t._prev = self.last
self.last = t
else
-- set the node as first node
self.first = t
self.last = t
end
-- increment the length of the list
self.length = self.length + 1
end
Step 2: Using setmetatable
modify list behavior when list is called to push elements.
setmetatable(list, { __call = function(_, ...)
local t = setmetatable({ length = 0 }, list)
for _, v in ipairs{...}
do t:push(v)
end
return t
end })
Step 3: Create iterator over list
Create an iterator to navigate through elements of the list.
-- iterate through the list
local function iterate(self, current)
-- if current is nil
-- set the current as first node
if not current then
current = self.first
-- if current is present
-- set current as current next
elseif current then
current = current._next
end
-- return current
return current
end
-- return the iterator
function list:iterate()
return iterate, self, nil
end
Step 4: Test Iterations on List
In list, we can insert objects,
-- define data tables
local mon = { "Mon" }
local tue = { "Tue" }
-- create a new list with two values
local l = list(mon, tue)
-- iterate throgh entries
for v in l:iterate() do
print(v[1])
end
-- create more data
local wed = { "Wed" }
local fri = { "Fri" }
-- add a table to the list
l:push(wed)
-- add a table to the list
l:push({ "Thu" })
-- add a table to the list
l:push(fri)
-- iterate throgh entries
for v in l:iterate() do
print(v[1])
end
Complete Example - Iterating elements of a List
Following is the complete example of inserting and traversing elements of a list.
main.lua
-- List Implementation
list = {}
list.__index = list
setmetatable(list, { __call = function(_, ...)
local t = setmetatable({ length = 0 }, list)
for _, v in ipairs{...}
do t:push(v)
end
return t
end })
-- push an element to the end of the list
function list:push(t)
-- move till last node
if self.last then
self.last._next = t
t._prev = self.last
self.last = t
else
-- set the node as first node
self.first = t
self.last = t
end
-- increment the length of the list
self.length = self.length + 1
end
-- iterate through the list
local function iterate(self, current)
if not current then
current = self.first
elseif current then
current = current._next
end
return current
end
function list:iterate()
return iterate, self, nil
end
-- define data tables
local mon = { "Mon" }
local tue = { "Tue" }
-- create a new list with two values
local l = list(mon, tue)
print("Original List")
-- iterate throgh entries
for v in l:iterate() do
print(v[1])
end
-- create more data
local wed = { "Wed" }
local fri = { "Fri" }
-- add a table to the list
l:push(wed)
-- add a table to the list
l:push({ "Thu" })
-- add a table to the list
l:push(fri)
print("List with added entries")
-- iterate throgh entries
for v in l:iterate() do
print(v[1])
end
Output
When we run the above code, we will get the following output−
Original List Mon Tue List with added entries Mon Tue Wed Thu Fri