This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Ehrlingby's profile picture

Detecting differences in tables?

Started by Ehrlingby, 18 January 2013 - 12:23 AM
Ehrlingby #1
Posted 18 January 2013 - 01:23 AM
Let's say that I have two tables.:

fruits = {"banana","apple"}
fruits2 = {"banana","apple","orange","tomato"}

How do I then make function that takes both tables, compares them with each other, detects the differences, and returns a table containing the table entries that are or are not present in the second table, in this case "tomato" and "orange".

Am I missing something extremely obvious?
theoriginalbit #2
Posted 18 January 2013 - 01:33 AM
so if you have


fruits1 = { "banana", "apple" }
fruits2 = { "orange", "tomato", "apple", "banana" }

would you still want it to return 'tomato' and 'orange' or would it be same index too?
Ehrlingby #3
Posted 18 January 2013 - 01:40 AM
Yes, I'd like it to return the actual difference; tomato and orange. The index aspect doesn't really matter in the project I'm planning.
theoriginalbit #4
Posted 18 January 2013 - 01:42 AM
Ok give me a minute to compile some advice :)/>
EDIT: Also any key value pairs? or just sequential?

Key value pair example

t = { ["someKey"] = someValue }

EDIT 2: Ok so here's a function that will compare and return the differences in a basic table


local function differences( t1, t2 )
  local rt = {}
  table.sort( t1 )
  table.sort( t2 )
  for i = 1, #t1 > #t2 and #t1 or #t2 do
	if t1[i] ~= t2[i] then
	  table.insert( rt, t1[i] )
	  table.insert( rt, t2[i] )
	end
  end
  return rt
end

EDIT 3: One for dictionaries


local function differencesDict( d1, d2 )
  local rd = {}
  for k, v in pairs( d1 ) do
    if not d2[k] then
      rd[k] = v
    elseif d2[k] ~= v then
      error( "Table conflict detected on key \""..k.."\"", 2 )
    end
  end
  for k, v in pairs( d2 ) do
    if not d1[k] then
      rd[k] = v
    end
  end
  return rd
end
Edited on 18 January 2013 - 01:36 AM
KaoS #5
Posted 18 January 2013 - 02:34 AM
here is a basic mock up I coded, one function for returning the common values and another for the differences


local function getSimilarities(t1,t2)
local tCombined={}
for k,v in pairs(t1) do
  local isThere=false
  for a,b in pairs(t2) do
   if v==b then isThere=true end
  end
  if isThere then table.insert(tCombined,v) end
end
return tCombined
end
local function getDifferences(t1,t2)
local tCombined={}
for k,v in pairs(t1) do
  local isThere=false
  for a,b in pairs(t2) do
   if v==b then isThere=true end
  end
  if not isThere then table.insert(tCombined,v) end
end
for k,v in pairs(t2) do
  local isThere=false
  for a,b in pairs(t1) do
   if v==b then isThere=true end
  end
  if not isThere then table.insert(tCombined,v) end
end
return tCombined
end

PS TheOriginalBIT: on line 5 of your code you could just say

  for i = 1, math.max(#t1,#t2) do
theoriginalbit #6
Posted 18 January 2013 - 02:37 AM
PS TheOriginalBIT: on line 5 of your code you could just say

  for i = 1, math.max(#t1,#t2) do
I always forget about that function… I do it all the time, make my own max, then later go an look and wonder why the hell i did it like that…

Your getDifferences loops a lot!
Edited on 18 January 2013 - 01:39 AM
KaoS #7
Posted 18 January 2013 - 02:46 AM
Your getDifferences loops a lot!

yeah -_-/> unfortunately you have to when you cannot use keys
theoriginalbit #8
Posted 18 January 2013 - 02:49 AM
yeah -_-/> unfortunately you have to when you cannot use keys
My one for sequential list loops once… for dictionaries twice… tested both and they worked fine…
KaoS #9
Posted 18 January 2013 - 02:57 AM
yeah -_-/> unfortunately you have to when you cannot use keys
My one for sequential list loops once… for dictionaries twice… tested both and they worked fine…

mine is not designed for combining similar keys, if the table contains the same value under any key it is detected so for example

YOUR CODE

differences({"orange","blue","green"},{"orange","blue","white"})
would return

{"green","white"}
which is perfect but if you said

differences({"blue","orange","green"},{"orange","blue","white"})
it would return

{"blue","orange","orange","blue","green","white"}
because it compares only 2 values at a time, it all depends on what you need it for really
theoriginalbit #10
Posted 18 January 2013 - 02:59 AM
because it compares only 2 values at a time, it all depends on what you need it for really


table.sort( t1 )
table.sort( t2 )
KaoS #11
Posted 18 January 2013 - 03:03 AM
ahhh didn't see that there, smart but still not completely functional. all you do is


differences({"aa","aa",the rest of your options},{"aa",the rest of your options})

and it will get confused again. but in almost every circumstance it will work (I'm sure it will work for OP)

EDIT: wait a second… if you just say

differences({1,2,3,4,5,6},{2,3,4,5,6,7})
it will sort both tables and compare 1==2; 2==3 etc the whole way…. :mellow:/>
Edited on 18 January 2013 - 02:06 AM
theoriginalbit #12
Posted 18 January 2013 - 03:06 AM

differences({"aa","aa",the rest of your options},{"aa",the rest of your options})
and it will get confused again. but in almost every circumstance it will work (I'm sure it will work for OP)
Mmmm true forgot about double of the same value… yeh it should be fine :)/> either one :)/>
KaoS #13
Posted 18 January 2013 - 03:11 AM
read the edit too. just realised something bad


EDIT: wait a second… if you just say

differences({1,2,3,4,5,6},{2,3,4,5,6,7})
it will sort both tables and compare 1==2; 2==3 etc the whole way…. :mellow:/>
theoriginalbit #14
Posted 18 January 2013 - 03:15 AM
read the edit too. just realised something bad


EDIT: wait a second… if you just say

differences({1,2,3,4,5,6},{2,3,4,5,6,7})
it will sort both tables and compare 1==2; 2==3 etc the whole way…. :mellow:/>
Hmmmm true… didn't think of that way… :mellow:/>
Ehrlingby #15
Posted 18 January 2013 - 05:01 AM
Thanks so much for the answers and different prospects! This will be one of the building blocks in my upcoming system. I might even post the results
on the forums.

Sneak peek (text) Logistics pipes and CC integration…
ChunLing #16
Posted 18 January 2013 - 12:30 PM
Uhuh. But there is a basic difficulty encountered here in that we don't know what counts as a difference. From what you've said, I would propose using a code that rebuilt one of the tables with the keys and values inverted, like so:
function kvinvert(lista)
	local listz = {}
	for k,v in pairs(lista) do
		listz[v] = k
	end
	return listz
end
You call this function with a table as an argument, and it returns a table that has every unique value in the input table as a key in the output table. The values in the output table will correspond to the keys of the last appearance of the value in the input table corresponding to the key in the output table. I'm a little mad at myself for even trying to explain that…it does what it does, okay?

Then you can use a loop to compare all the values in a table to the keys of the inverted table (finding out if the value match occurred at all, and optionally seeing if the indexes matched as well), and do what you like with the results (returning a pair of tables seems to be what you want, but I can't tell for sure).

Just for the record, obviously this is only going to work for tables have values which can be used as indexes.
Edited on 18 January 2013 - 11:32 AM