Search code examples
listluacomparison

Checking values across multiple location and returning a match only if the sources are unique


Lets say I have a list of Vendors: Asda, Tesco, Spar.

And I have a list of Sources (or suppliers in this analogy): Kellogg, Cadbury, Nestle, Johnsons, Pampers, Simple, etc. (there is a defined list of around 20).

Elsewhere in the flow of data. I am returning a result, which is Yes/No for each vendor, for multiple different things.

For example: Asda: ukOnly = "Yes"; Spar: ukOnly = "No" etc.

In this specific section, I am collating results.

Mostly it doesn't matter if the sources from the vendors overlap. So I can just say:

function concatResults(x) -- concats the result of "x" for each vendor
 local pathAsda = *this is where I call the path location specific to Asda*
 local pathTesco = *this is where I call the path location specific to Tesco*
 local pathSpar = *this is where I call the path location specific to Spar*
   if (pathAsda == "Yes" or pathTesco == "Yes" or pathSpar == "Yes") then
    return "Yes"
   else
    return "No"
   end
end

ukOnlyAgr = concatResults("ukOnly")

Great!

Now, say I want to do something more comple.

I want to know how many unique suppliers are providing chocolate and cereal. The example below is being used further up the process to produce a fact suppliesSweet, only if there is at least two sources (suppliers) involved and they must be at least supplying chocolate. This will be done for each vendor separately (please assume I have already defined my variables based on the input data:

if (suppliesChoc > 0 and suppliesCereal > 0 and numSources > 1) or (suppliesChoc > 1) then
  then suppliesSweet = "Yes"
else suppliesSweet = "No"
end

Not a problem yet.

The issue comes when I try to aggregate these results across vendors (as I did before with ukOnly).

I already have the following function being used:

table.contains = function(t, value) -- Finds if "value" exists inside the table "t"
    for index = 1, #t do
        if t[index] == value then
            return index    
        end
    end
end

And was thinking of creating this:

table.overlap = function(t,g) -- Finds if tables "g" and "t" have any overlapping values
    for i=1,#t do
        if table.contains(g,t[i]) then
           return true
        else
           return false
        end
    end
end

But I'm just not sure where to go from there.

You can assume I have already got a list of unique sources for each vendor and I don't mind if we're over restrictive. I.e. if any sources overlap between the two vendors, that would invalidate the entire result.

You can also assume I have each "fact": suppliesChoc, suppliesCereal, numSources and suppliesSweet for each vendor returned separately.


Solution

  • I believe your looking for the intersection of two sets.

    https://en.wikipedia.org/wiki/Intersection_(set_theory)

    One set being your vendor's suppliers and the other being the suppliers who supply sweets.

    local vendors = {
      Asda = {Kellogg = true, Cadbury = true, Nestle = true, Johnsons = true, Pampers = true, Simple = true}, 
      Tesco = {Kellogg = true, Cadbury = true, Nestle = true, Johnsons = true},
      Spar ={Nestle = true, Johnsons = true, Pampers = true, Simple = true}
    }
    
    function intersection(s1, s2)
      local output = {}
      
      for key in pairs(s1) do
        output[#output + 1] = s2[key]
      end
    
      return output
    end
    
    local sweetSuppliers = {Kellogg = true, Cadbury = true, Nestle = true}
    
    for name, suppliers in pairs(vendors) do
      local result = intersection(sweetSuppliers, suppliers)
      
      print(name .. " has " .. #result .. " sweets suppliers")
    end
    

    Here are some examples of a libraries for handling sets:

    odkr's properset.lua

    Windower's sets.lua

    Both can give you an idea of how you can use sets to accomplish things like intersection, and much more