Comparing 2 objects

BlitzMax Forums/BlitzMax Programming/Comparing 2 objects

KamaShin(Posted 2005) [#1]
How can I compare 2 objects, not even knowing in advance what will be the type of these two??? would the following function be ok??

Function Compare:Int(o1,o2)
     Return (o1 = 02)
End Function

while o1 and o2 could be both strings or arrays or TImage or even of different types... is just using "=" sufficient? what if o1 and o2 are user declared type?


PowerPC603(Posted 2005) [#2]
This won't work, as you've declared the parameters of your function as Ints, you will get an "Unable to convert from ... to 'Int'" error.

You could use this instead:
Type test1
End Type

Type test2
End Type

testa:test1 = New test1
testb:test2 = New test2
testc:test1 = testa
testd:test1 = New test1

Print CompareObjects(testa, testc)

Function CompareObjects(o1:Object, o2:Object)
	Return (o1 = o2)
End Function


Note that this function only returns "1" when both o1 and o2 point to the same object (array, string, custom type instance, ...).

I can however accept anything (ints, strings, arrays, ...).
It prints "0" if both variables (o1 and o2) don't point to the same object.
In this example, testa and testc point to the same object and therefore the function returns "1".
If you would supply testa and testd to the function, it returns "0", as testa isn't pointing to the same test1-instance as testd (the function just compares the memory-address of both objects, which isn't the same for testa and testd).


KamaShin(Posted 2005) [#3]
yep but the problem is that I can have o1 and o2 being "equal" even if they're not pointers of the same object...

having o1 = o2 means that all their fields have the same value... so I was wondering if there was a way to compare 2 objects this way without knowing what their fields will be, but I guess not...


PowerPC603(Posted 2005) [#4]
I don't think this is possible.
I guess you'll have to figure out which type the object really is and then check for each field of that objecttype.

Then this function could become very long, as you would have to compare each field of each object for each objecttype in your program.


teamonkey(Posted 2005) [#5]
Every object has a method called Compare(), described in the Language->Objects section of the docs. You can write your own Compare() method if you need to.


PowerPC603(Posted 2005) [#6]
Blitz3D had the command Str, which could do what you wanted.

; Blitz3D code

Type test
	Field num
End Type

testa.test = New test

testa\num = 5

Print Str testa
WaitKey()

This prints "[5]".

; b3D code with Compare function
Type test
	Field num
End Type

testa.test = New test
testb.test = New test

testa\num = 5
testb\num = 6

Print Str testa
Print Compare(testa, testb)
WaitKey()



Function Compare(o1.test, o2.test)
	o3$ = Str o1
	o4$ = Str o2

	If o3 = o4 Then Return True Else Return False
End Function


Unfortunately, this doesn't work in BMax.
Str creates a string, with all contents of all fields in the object, separated by comma's and between [].
This could be another thing that could be added to BMax.
Then you would just compare both outputs of the Str function to see if they match.

Try the above code in B3D and change the line "testb\num = 6" into "testb\num = 5" and see what it does.
This would be what you want, KamaShin.

This code (in BMax) does what you need (thanks to the idea of teamonkey):
Type test
	Field num%
	Field text$

	Method Compare(o1:Object)
		' Try to cast the given object to this object-type
		o2:test = test(o1)

		' If casting was succesfull (the object passed is a "test"-instance)
		If o2 Then
			' Compare all fields
			If (num = o2.num) And (text = o2.text) Then Return True Else Return False
		Else
			Return False
		EndIf
	End Method
End Type

testa:test = New test
testb:test = New test

testa.num = 5
testa.text = "Hello"

testb.num = 7
testb.text = "Hello"

Print testa.Compare(testb)

Play with the field-value a bit and see.
This code will have to be changed everytime you add a new field to the type "test", that's the downside of it (compared to the B3D code).

But it could be a problem when the passed object to the Compare-method is a derived type of "test".
Then there would be more fields inside your object and this method only checks the fields specific to the "test"-type.


KamaShin(Posted 2005) [#7]
yep I guess the B3D Str solution would be the one...

<teamonkey> that wouldn't work cause... well I m making a small mod that add a few functions for arrays (like append, insert or remove)... what I want to do is create a remove function that can have an array and the index of the object to remove as parameters, and a second version of remove that has the array and the object you want to remove... inside the second version I have to test if the passed object is "equal" to one of the objects in the array and if so remove it... I guess I'll have to stick with the remove object only if these are pointers to the very same object...


KamaShin(Posted 2005) [#8]
yep I guess the B3D Str solution would be the one...

<teamonkey> that wouldn't work cause... well I m making a small mod that add a few functions for arrays (like append, insert or remove)... what I want to do is create a remove function that can have an array and the index of the object to remove as parameters, and a second version of remove that has the array and the object you want to remove... inside the second version I have to test if the passed object is "equal" to one of the objects in the array and if so remove it... I guess I'll have to stick with the remove object only if these are pointers to the very same object...

(hope this makes sens :) )


teamonkey(Posted 2005) [#9]
<teamonkey> that wouldn't work cause... well I m making a small mod that add a few functions for arrays (like append, insert or remove)... what I want to do is create a remove function that can have an array and the index of the object to remove as parameters, and a second version of remove that has the array and the object you want to remove... inside the second version I have to test if the passed object is "equal" to one of the objects in the array and if so remove it... I guess I'll have to stick with the remove object only if these are pointers to the very same object...

I think the only way you can do that is to use the Compare() method and make sure that every Object you place place in the array overrides that method. Either that or make sure it overloads the ToString() method.

If you don't know the type of either object you can't do a byte-by-byte comparison of the object because you don't know the size of the objects or what fields there are and how they line up.
Function compare(t1:Object, t2:Object)
	Print SizeOf(t1)
	Print SizeOf(t2)
End Function

Will print 0 for each because the size of an Object is 0. You'd need to cast the Object to something else to find the right size and that relys on you knowing what type the object is beforehand.


FlameDuck(Posted 2005) [#10]
You could use a hashing scheme, if you can find a good and sinple algorythm that produces the same hash for the same data in random order. The question is: do you need to have two objects with the same values in different fields be equal aswell? For instance would an object where x=10,y=5 be "equal" to an object where x=5,y=10? If not then writing a simple hashing algorythm to generate one hash for all fields would solve your problem.


KamaShin(Posted 2005) [#11]
hmmm never set a foot in the world of hashing so I m not even sure how this works... (don't event get a general idea)... what's hashing basically?


FlameDuck(Posted 2005) [#12]
what's hashing basically?
A "hash" is a non-reversible fixed-length representation of an arbitrary ammount of data. Aspects of a good hashing algorithm include that small variations in input data, will give large variations in the hash value. Additionally a good hashing algorithm should provide as few as possible hash collisions (where different data equals the same hash value) as possible with regards to expected data.


KamaShin(Posted 2005) [#13]
aaaaah I think I see what you mean... yeah silly me it's the same word in french and I didn't see the link... well assuming hash-table refers almost to the same "hash". But I'm not sur how I can use this for comparing unkown object...


Dreamora(Posted 2005) [#14]
You hash all your objects and compare their hash values


KamaShin(Posted 2005) [#15]
that's only doable with MY objects... since i'm writing a module, the procedures I'm writing should be usable for any users on any objects... well, I decided to use the "=" symbol and consider that 2 objects are "equal" if they reference to the same thing in memory...


Dreamora(Posted 2005) [#16]
This is why the method has to be implemented in ANY object that should be capable of this comparision.

Just give them a method which is called "hash:int ()" that returns the hash of this object.


FlameDuck(Posted 2005) [#17]
the procedures I'm writing should be usable for any users on any objects.
In that case you can only do this using runtime reflection. BlitzMAX does not support a reflection mechanism as far as I'm aware.


marksibly(Posted 2005) [#18]
Hi,

I think you should just use the 'Compare' method.

This exists for every object, and by default just does an address comparison. This at least gives you the ability to do the same thing as 'obj1=obj2', by using obj1.Compare(obj2)=0.

Strings override Compare to do a proper character by character comparison, so you also get proper string behaviour 'for free'.

And of course, other types can provide their own Compare.

Have a look at the mod/brl.mod/linkedlist.mod/linkedlist.bmx source to see how Compare is used to provide a Sort method for lists.


KamaShin(Posted 2005) [#19]
hmmm I hadn't thought about that... thinking compare was merely a replacement for "="... and it wouldn't require much change in my code too... okay... sold :) I buy it :)
thanks for the tip :)