Lua - Searching in Lists



In order to search a list, we need to traverse and check if given element is present or not. To check an element in a list, we'll be using two approaches.

  • Create Iterator and search element using for loop

  • Navigate the list using while loop and search element.

Using iterator

Let's build an iterator which can return the next element of the list to do the traversing and check the element in for loop. 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:iterator()
   return iterate, self, nil
end

We can use list:iterator() function to iterate the list which will return the next element when invoked in a for loop as shown below:

itemToSearch = "wed"
found = false
-- iterate throgh entries
for v in l:iterator() do 
   if v[1] == itemToSearch then
      found = true
	  break
   end
end

if found then
   print(itemToSearch, "is present in the list.")
else
   print(itemToSearch, "not present")
end

Complete Example - Searching an element of a List using iterator and for loop

Following is the complete example of inserting and searching 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:iterator()
   return iterate, self, nil
end

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

itemToSearch = "Wed"
found = false
-- iterate throgh entries
for v in l:iterator() do 
   if v[1] == itemToSearch then
      found = true
	  break
   end
end

if found then
   print(itemToSearch, "is present in the list.")
else
   print(itemToSearch, "not present.")
end

itemToSearch = "Sat"
found = false
-- iterate throgh entries
for v in l:iterator() do 
   if v[1] == itemToSearch then
      found = true
	  break
   end
end

if found then
   print(itemToSearch, "is present in the list.")
else
   print(itemToSearch, "not present")
end

Output

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

Wed	is present in the list.
Sat	not present.

Using While Loop

We can navigate through the list using while loop and return true if element found else return true.

-- search an element in list,
-- returns true if found else returns false
function list:search(value)
   found = false
   -- set current as first node
   current = self.first

   -- navigate till end of the list
   while current._next do
      -- if element found   
      if current[1] == value then
         found = true
         break
      end
      -- point to next node
      current = current._next
   end
   return found
end

We can pass an item to search in this method and return true/false based on item's availablilty in the list.

Complete Example - Searching an element of a List using while loop

Following is the complete example of inserting and searching 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

-- search an element in list,
-- returns true if found else returns false
function list:search(value)
   found = false
   -- set current as first node
   current = self.first

   -- navigate till end of the list
   while current._next do
      -- if element found   
      if current[1] == value then
         found = true
         break
      end
      -- point to next node
      current = current._next
   end
   return found
end

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

itemToSearch = "Wed"
found = l:search(itemToSearch)

if found then
   print(itemToSearch, "is present in the list.")
else
   print(itemToSearch, "not present.")
end

itemToSearch = "Sat"
found = l:search(itemToSearch)

if found then
   print(itemToSearch, "is present in the list.")
else
   print(itemToSearch, "not present.")
end

Output

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

Wed	is present in the list.
Sat	not present.
Advertisements