How to use SortList for your own types

BlitzMax Forums/BlitzMax Tutorials/How to use SortList for your own types

Phish(Posted 2005) [#1]
So you thought that SortList could only be used for integers and strings? Wrong! You can order any type with it. All you need to do is implement/override the Compare method within your type. When compared with another object, you just return whether it is "less than", "greater than" or "equal to" the other object, with a number less than, greater than, or equal to zero.

See this example code:
Type sprite
	Field order
	
	Method Compare(otherObject:Object)
		s:sprite = sprite(otherObject)
		If Not s Then Return 1			' Object not a sprite: define greater than any sprite
		Return order - s.order
	End Method
End Type

' ----------------------------

SeedRnd MilliSecs()
sprite_list:TList = New TList

' Create a list of randomised sprites
For i=1 To 100
	s:sprite = New sprite
	s.order = Rand(100)
	ListAddLast sprite_list, s
Next

' Make sure it doesn't fall over if something odd is added
ListAddLast sprite_list, "Object that is not a sprite"

' Sort the list!
SortList sprite_list

' Check to see if it is sorted correctly
For s = EachIn sprite_list
	Print s.order
Next


We need to implement the Compare method because that is what the SortList command uses. We are sorting the sprites in order of the "order" field in the sprite type.

Try running the code - the sprites are now ordered correctly!


fredborg(Posted 2005) [#2]
Hey! That's a super trick. Thanks a lot!


flying willy(Posted 2005) [#3]
This is superb.


flying willy(Posted 2005) [#4]
Problem lads...
Type map 
	Field image,x#,y#,z#,angle#
	
	'override default sort method
	Method Compare(otherObject:Object)
		m:map = map(otherObject)
		If Not m Return 1
		Return z - m.z 'z is the sort field... make anything you like
	End Method
		
End Type


I'm trying to sort my things by Z and the Z value is very small (floating point) ... and the routine seems to only work with ints.

What would I need to do to fix this?


flying willy(Posted 2005) [#5]
Solved... it was a float and I can't change the method return value as we are overriding.

Therefore surreal suggested that I try If z > m.z Return 1 Else Return -1 instead, which works a treat.

In short, change the original sprite routine to read:
If order > s.order Return 1 else Return -1


To make it compatible with floating point numbers.


fredborg(Posted 2005) [#6]
If you are using floating point z depths to sort by, you could simply go: Return Sgn(z-m.z)


taxlerendiosk(Posted 2005) [#7]
That would also fix it for identically valued objects, which should return 0 not -1.


flying willy(Posted 2005) [#8]
Thank you :)


Mark Tiffany(Posted 2005) [#9]
That would also fix it for identically valued objects, which should return 0 not -1.

I believe that the default behaviour for objects will do this without having to over-ride it. i.e. Compare by default will compare the integer value returned by the object when used in old-style Blitz fashion. Although sorting in this fashion is next to useless, it is useful for inequality testing, which also uses the Compare method.


Zakk(Posted 2009) [#10]
Beware.
http://www.blitzbasic.com/Community/posts.php?topic=87418
Best not to override methinks.