Lua - List length



List is a dynamic data structure and in order to keep track of size of the list, we can keep a length as state of the list. We can increment the length by 1 whenever an element is added to the list and decrement it by 1 when an element is removed.

We'll build the list and then add method to insert an element, remove an element and get size of 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 remove() method

Create remove(t) to remove a given element.

-- remove a specific element, t
function list:remove(t)
   -- if node to delete has next node
   -- update the pointers of prev and next nodes
   if t._next then
      if t._prev then
         t._next._prev = t._prev
         t._prev._next = t._next
      else
         -- this was the first node
         t._next._prev = nil
         self._first = t._next
       end
   elseif t._prev then  -- if node has prev node only
      -- this was the last node
      t._prev._next = nil
      self._last = t._prev
   else
      -- this was the only node
      self._first = nil
      self._last = nil
   end

   t._next = nil
   t._prev = nil
   self.length = self.length - 1
end

Step 4: Get Length of the List

Create a function to get length of the list

function list:size()
   return self.length
end

Step 5: Test Length of the List

In list, insert and remove object and check the length of the list

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

print("Original List Size:", l:size())

-- remove an element
l:remove({"Wed"})
print("List Size after removing one element:", l:size())

-- add an Element
l:push({"Sat"})
print("List Size after adding one element:", l:size())

Complete Example - Size of a List

Following is the complete example of checking size of a list after adding/removing element.

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

-- remove a specific element, t
function list:remove(t)
   -- if node to delete has next node
   -- update the pointers of prev and next nodes
   if t._next then
      if t._prev then
         t._next._prev = t._prev
         t._prev._next = t._next
      else
         -- this was the first node
         t._next._prev = nil
         self._first = t._next
       end
   elseif t._prev then  -- if node has prev node only
      -- this was the last node
      t._prev._next = nil
      self._last = t._prev
   else
      -- this was the only node
      self._first = nil
      self._last = nil
   end

   t._next = nil
   t._prev = nil
   self.length = self.length - 1
end

function list:size()
   return self.length
end

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

print("Original List Size:", l:size())

-- remove an element
l:remove({"Wed"})
print("List Size after removing one element:", l:size())

-- add an Element
l:push({"Sat"})
print("List Size after adding one element:", l:size())

Output

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

Original List Size:	5
List Size after removing one element:	4
List Size after adding one element:	5
Advertisements