1
votes

In Lua v. 5.2, how can I get the complement of two tables' keys that are all strings?

Optimally, I'd like to have a function something like:

    table.complement ( t1, t2 )

... where the return is a table that is the complement of key/value pairs in table 1 and table 2. That is, the returned table contains only the keys that are not in both tables.

The use case staring me in the face is a script for the NoteCase Pro outliner that will fetch a "before" list of unique sibling node IDs (22 chars each) before performing an operation that will split the current node into multiple sibling nodes, fetch a new "after" list of sibling node IDs, reduce that list to the complement of the two lists, then demote the newly-created nodes to become child nodes or the original current node in the hierarchy.

2
Can you elaborate on the complementing of key-value? - hjpotter92
"complement"? Do you mean t1 set-minus t2? - Cubic
Edited to make it more clear. I mean the set of key/value pairs that do not exist in both tables, i.e, the IDs for the newly-created nodes. - user2182586
It is usually referred to as "symmetric difference". - Egor Skriptunoff

2 Answers

4
votes
local function symm_diff(t1, t2)
  local t = {}
  for k, v in pairs(t1) do
    if t2[k] == nil then t[k] = v end
  end
  for k, v in pairs(t2) do
    if t1[k] == nil then t[k] = v end
  end
  return t
end
0
votes

There isn't any reason why you couldn't write this yourself... something like this?

function table.complement(t1, t2)
    local res = {}

    for _,v1 in pairs(t1) do
        local found = false
        for _,v2 in pairs(t2) do
            if (v1 == v2) then
                found = true
                break
            end
        end
        if not found then table.insert(res, v1) end
    end

    for _,v2 in pairs(t2) do
        local found = false
        for _,v1 in pairs(t1) do
            if (v2 == v1) then
                found = true
                break
            end
        end
        if not found then table.insert(res, v2) end
    end

    return res
end

local t1 = {"stuff", "more", "things"}
local t2 = {"stuff", "junk", "things"}

table.foreach(table.complement(t1, t2), print)

which prints

1    more
2    junk