Lua - Accessing List Elements



A Linked list contains nodes where each node is pointing to next node. So in order to access any element, we need to traverse the list. One easy way to store references to first and last element of the list and then we can refer them easiy. For example, first node can be accessed easily as shown below−

function list:getFirst()
   -- if first is nil then return
   if not self.first then
      return 
   end
   return self.first
end

We'll build the list and then add method to insert an element, get first element, get last element of the list and an iterator to traverse 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: Get first element

Create a function to get first element

function list:getFirst()
   -- if first is nil then return
   if not self.first then
      return 
   end
   return self.first
end

Step 4: Get Last element

Create a function to get last element

function list:getLast()
   -- if last is nil then return
   if not self.last then
      return 
   end
   return self.last
end

Step 5: 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 6: Test Accessing elements on List

In list, we can insert objects,

-- create a new list with values
local l = list({ "Mon" }, { "Tue" }, { "Wed" }, { "Thu" }, { "Fri" })

print("Original List")
-- iterate throgh entries
for v in l:iterate() do 
   print(v[1]) 
end

-- get first element
print("First Element: " , l:getFirst()[1])

-- get last element
print("Last Element: " , l:getLast()[1])

Complete Example - Accessing 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

function list:getLast()
   -- if last is nil then return
   if not self.last then
      return 
   end
   return self.last
end

function list:getFirst()
   -- if first is nil then return
   if not self.first then
      return 
   end
   return self.first
end

-- create a new list with values
local l = list({ "Mon" }, { "Tue" }, { "Wed" }, { "Thu" }, { "Fri" })

print("Original List")
-- iterate throgh entries
for v in l:iterate() do 
   print(v[1]) 
end

-- get first element
print("First Element: " , l:getFirst()[1])

-- get last element
print("Last Element: " , l:getLast()[1])

Output

When we run the above code, we will get the following output−

Original List
Mon
Tue
Wed
Thu
FriFirst Element: 	Mon
Last Element: 	Fri
Advertisements