Lua - Concatenate List Elements



Cancatenating lists means merging elements of two or more lists. We can achieve the same easily using below pseudo code. First we can create an empty list, iterate elements of each list and push them to the empty list. Now the empty list is the merged list.

-- create an empty list    
local mergedList = list()

-- iterate first list items and push to merged List
for v in list1:iterate() do    
   mergedList:push(v) 
end

-- iterate second list items and push to merged List
for v in list2:iterate() do    
   mergedList:push(v) 
end

We'll build the list and then using concat methods, we'll merge two and more list together.

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 a concat function

Create a function to concat two list and return the merged list

-- function to concat two list
function concat(list1, list2)
    
   -- create an empty list    
   local mergedList = list()

   -- iterate first list items and push to merged List
   for v in list1:iterate() do    
      mergedList:push(v) 
   end

   -- iterate second list items and push to merged List
   for v in list2:iterate() do    
      mergedList:push(v) 
   end
   
   -- return the merged list
   return mergedList
end

Step 4: Create iterator over list and update complete list during iteration.

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 5: Test Concatenation of elements on List

Now we can concat lists as shown below

-- create two lists with two values each
local l1 = list({"Mon"}, {"Tue"})
local l2 = list({"Wed"}, {"Thu"})

local l3 = concat(l1, l2)

-- iterate throgh entries
for v in l3:iterate() do 
    print(v[1]) 
end

Complete Example - Concat two and more lists

Following is the complete example of concatenating two and more lists.

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 to concat two list
function concat(list1, list2)
    
   -- create an empty list    
   local mergedList = list()

   -- iterate first list items and push to merged List
   for v in list1:iterate() do    
      mergedList:push(v) 
   end

   -- iterate second list items and push to merged List
   for v in list2:iterate() do    
      mergedList:push(v) 
   end
   
   -- return the merged list
   return mergedList
end

-- create two lists with two values each
local l1 = list({"Mon"}, {"Tue"})
local l2 = list({"Wed"}, {"Thu"})

-- merged two lists
local l3 = concat(l1, l2)

-- iterate throgh entries
for v in l3:iterate() do 
    print(v[1]) 
end

local l4 = list({"Fri"}, {"Sat"}, {"Sun"})
local l5 = concat(l3, l4)

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

Output

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

Mon
Tue
Wed
Thu
-----
Mon
Tue
Wed
Thu
Fri
Sat
Sun
Advertisements