Search code examples
luaduplicateslua-tablenested-table

Remove duplicate tables in a nested table. Lua


Before you mark this question as duplicate of this please read the whole thing:

I have a table in Lua which is a table of tables something like the below one and I want to remove all the duplicate tables in it.

table1 = {{1, 2, 3}, {1, 2, 3}, {1, 2, 3, 4}}

What I want to do is to remove the duplicate tables and use only one. The result should be like the one below

table2 = {{1, 2, 3}, {1, 2, 3, 4}}

I tried a lot of methods I found online and some of my own and I couldn't get to do it.

Here is what I tried last

local test = {1,2,4,2,3,4,2,3,4,"A", "B", "A"}
local hash = {}
local res = {}

for _,v in ipairs(test) do
   if (not hash[v]) then
       res[#res+1] = v -- you could print here instead of saving to result table if you wanted
       hash[v] = true
   end

end

-- Here the test is the input, and res is the output table without 
-- any duplicates but this works only for values in it and not for
-- nested tables.

Please help me out.


Solution

  • Let's take pen and paper and think.

    What do we have?

    A table that contains multiple tables. According to your example those inner tables are sequences. So they only have consecutive integer keys starting from 1. The inner tables' elements are either strings or numbers.

    You want to remove duplicate inner tables that is a table that has the same elements as another table before it.

    So what do we have to do?

    We need to go through our table and check each element and ask if we have seen this inner table's contents before.

    So we make a list of sequences that we have seen before.

    1) Check if the next element is already on the list.
    2) If it is on the list, remove it, else put it on the list.
    3) back to 1 
    

    Now translate that into Lua

    local table1 = {{1, 2, 3}, {1, 2, 3}, {1, 2, 3, 4}}
    
    -- make a list to add what we already have seen
    local list = {}
    -- make a list of unique items as it is easier than removing items from our input list
    local results = {}
    -- go over the list and check each element
    for i, innerTable in ipairs(table1) do
      -- convert it to a string representation so we add it to our list easily
      local serialized = table.concat(innerTable, "\x1f")
      -- only if it is not on our list yet
      if not list[serialized] then
        -- add it to the list
        table.insert(results, innerTable)
        -- add the item to the result list
        list[serialized] = true
      end
    end
    
    -- print the results
    for i,v in ipairs(results) do print(v) end