Search code examples
arrayslua

How to i compare the value in array for similar regardless the order of index


I am new to Lua and love using array but not good at it. The code that I have is a simple array comparison between 2 array. but what I wanted to do was to compare any value inside the array between number and number1. as showed in "my current code" below, there should be 2 digit in different index from both side and I want to print "2 number matches!" and etc.

I also want to compare from an array1 with {1,2,4} and array2 with {2,1,4} and print("Match!"). A simple "==" did not work as it compare each value from the same index of both array1 and array2. I tried googling all this problem of mine but didn't get what I wanted... Sorry, just learned array not long ago

my current code

local number = {5,6,7,8,9,4}
local number1 = {3,2,4,6,1}

if number == number1 then
    print("Matched!")
else
    print("No Match")
end

Expectation (example of what i wanted to have but in code)

local array1 = {5,6,7,8,9,4}
local array2 = {3,2,4,6,1}
local array3 = {6,5,8,4,9,7}

if array1 == array2 then
    print("Matched!")
elseif array2 has x amount of similarities to array1 
    print(x .."Matched!") -- this will print 2 or more matches
else
   print("No Match!")
end

if array3 have similar value regardless of the index of array1 then
    print("Matched!")
else
   print("No Match!")
end


Solution

  • You can convert your arrays into sets, implemented as item => true tables, and use set arithmetics:

    local set_mt = {}
    
    -- Set difference (set1 - set2):
    function set_mt.__sub (set1, set2)
        local diff = {}
        for value, _ in pairs (set1) do
            if not set2 [value] then
                diff [value] = true
            end
        end
        return setmetatable (diff, set_mt)
    end
    
    -- Set intersection (set1 ^ set2):
    function set_mt.__pow (set1, set2)
        local intersect = {}
        for value, _ in pairs (set1) do
            if set2 [value] then
                intersect [value] = true
            end
        end
        return setmetatable (intersect, set_mt)
        --[[ Also possible:
        return set1 - (set1 - set2)
        --]]
    end
    
    -- Set cardinality (#set):
    function set_mt.__len (set)
        local len = 0
        for value, _ in pairs (set) do
            len = len + 1
        end
        return len
    end
    
    -- Set equality (set1 == set2):
    function set_mt.__eq  (set1, set2)
        return #(set1 - set2) == 0 and #(set2 - set1) == 0
        --[[ Also possible:
        return #set1 == #set2 and #(set1 ^ set2) == #set1
        --]]
    end
    
    --[[ Also possible, though not required by the task:
        union, as __add,
        cartesian product as __mul,
        is subset of as __le,
        serialisation as __tostring,
        absolute complement as __umn, if there is a universum, though it will make everything more complex.
    --]]
    
    local function toset (array)
        local set = {}
        for _, value in ipairs (array) do
            set [value] = true
        end
        return setmetatable (set, set_mt)
    end
    
    -- Test:
    local array1 = {5,6,7,8,9,4}
    local array2 = {3,2,4,6,1}
    local array3 = {6,5,8,4,9,7}
    
    local set1, set2, set3 = toset (array1), toset (array2), toset (array3)
    
    local x = #(set2 ^ set1)
    
    if set1 == set2 then
        print 'array1 and array2 matched!'
    elseif x >= 2 then
        print ('array2 has ' .. tostring (x) .. ' matches in array1') -- this will print 2 or more matches
    else
        print 'No Match!'
    end
    
    if set3 == set1 then
        print 'array3 and array1 matched!'
    else
        print 'No Match!'
    end