Lua - Slicing Lists
In Lua, there is no inbuild support for slicing array/table but using table.unpack() function, we can achieve the same. And using the same technique we can slice a linked list as well. We'll be using inbuilt function table.unpack() which accepts an array and gives the sliced array. We need to convert the linked list to an array, get the sliced array using table.unpack() and then rebuild the linked list from the sliced array as shown in steps below:
Get an Array from the List
Iterate through each entry of the list and store each value into the array.
-- convert list to an array
function list:toArray()
local array = {}
local current = self.first
while current do
table.insert(array, current[1])
current = current._next
end
return array
end
Slice the array using table.unpack() function
-- get array from the list
local arr = l:toArray()
-- unpack the array with start/end indexes
local slicedArray = {table.unpack(arr, 2, 4)}
Rebuild the list using sliced array
-- create a new list
l = list()
-- push the slicedArray entries into the list
for _, v in ipairs(slicedArray) do
l:push({v})
end
Complete Example - Slicing the linked List
In below example, we're slicing the linked list using above steps. We created a linked list of 6 values and then sliced it from 2nd to 4th value.
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
-- convert list to an array
function list:toArray()
local array = {}
local current = self.first
while current do
table.insert(array, current[1])
current = current._next
end
return array
end
-- create a new list with values
local l = list({ "A" },{ "B" }, { "C" },{ "D" } , { "E" }, { "F" })
print("Original List")
-- iterate throgh entries
for v in l:iterator() do
print(v[1])
end
-- get array from the list
local arr = l:toArray()
-- unpack the array with start/end indexes
local slicedArray = {table.unpack(arr, 2, 4)}
-- create a new list
l = list()
-- push the sliced entries into the list
for _, v in ipairs(slicedArray) do
l:push({v})
end
-- print the sliced list
print("Sliced List")
-- iterate throgh entries
for v in l:iterator() do
print(v[1])
end
Output
When we run the above code, we will get the following output−
Original List A B C D E F Sliced List B C D
Advertisements