Sorting diddy arraylist by floats?

Monkey Forums/Monkey Programming/Sorting diddy arraylist by floats?

ondesic(Posted 2013) [#1]
I know the main comparator returns an int. How can I sort an object by a Float field?

Thanks


therevills(Posted 2013) [#2]
The return parameter for the Comparator is used in the sort method. You use the comparator on anything you like:

Class Sprite
	Field y:Float
End

Class SpriteComparator Extends IComparator
	' Compare should return 0 if the items are equal, a negative value if o1 < o2, and a positive value if o1 > o2
	Method Compare:Int(o1:Object, o2:Object)
		Local c1:Sprite = Sprite(o1)
		Local c2:Sprite = Sprite(o2)
		
		If c2 = c1 Return False
		
		If c1.y = c2.y
			Return True
		End
		
		Return Sgn(c1.y - c2.y)
	End
End

Global spriteList:ArrayList<Sprite> = New ArrayList<Sprite>

spriteList.Comparator = New SpriteComparator()

spriteList.Sort()



ondesic(Posted 2013) [#3]
Yes, it compares, but only to the Int level. If you compare 7.1, 7.2, 7.3 it will return them all as 7. Does this make sense?


muddy_shoes(Posted 2013) [#4]
No, as the return value isn't the difference between the values, it's just representative of which is larger (or, more generally, the desired ordering). I suggest you read the code that therevills posted and take note of the comment doc:

' Compare should return 0 if the items are equal, a negative value if o1 < o2, and a positive value if o1 > o2



ondesic(Posted 2013) [#5]
muddy_shoes,
Let's just try a test? Try this and tell me what you get.

Import diddy

Class testFloat Implements IComparable
	Field flo:Float
	Field nothing:Int
	
	Method New(ff:Float)
		flo = ff
	End
	
	Method Compare:Int(o:Object)
		Return flo - testFloat(o).flo
	End

	Method CompareBool:Bool(o:Object)
		Return Self = o Or flo = testFloat(o).flo
	End
End

Class game Extends App
	Field mytest:ArrayList<testFloat> = New ArrayList<testFloat>

	Method OnCreate:Int()
		mytest.AddLast(New testFloat(4.6))
		mytest.AddLast(New testFloat(4.7))
		mytest.AddLast(New testFloat(4.8))
		
		mytest.Sort()
		
		Print mytest.Get(0).flo + "  " + mytest.Get(1).flo + "  " + mytest.Get(2).flo

	End
End

Function Main:Int()
	g = New game
	Return 0
End


I get "4.8 4.6 4.7" Hardly sorted.

Now if I go into diddy's collections.monkey and change Int to Float:
Interface IComparable
	Method Compare:Int(o:Object)
	Method Equals:Bool(o:Object)
End

to
Interface IComparable
	Method Compare:Float(o:Object)
	Method Equals:Bool(o:Object)
End


Change the Compare method in the testFloat class to :Float
Now try the code again.
I get "4.6 4.7 4.8"


muddy_shoes(Posted 2013) [#6]
I don't need to try a test. You're simply not creating a comparator that complies with the expected interface. To repeat the comment for the third time, the interface expects an Int that is:

0 if the items are equal, a negative value if o1 < o2, and a positive value if o1 > o2


It doesn't matter if you're sorting Floats, Strings, 3D vectors, colours, employee records or golf clubs -- it expects an integer that defines the sorting order.


Jesse(Posted 2013) [#7]
@ondesic,

you need to pay more attention the example by therevills.

It needs to be something like this:

Import diddy

Class testFloat
	Field flo:Float

	Method New(ff:Float)
		flo = ff
	End
	
End Class

'************************* this is required *******************

Class floatComparator Extends IComparator
	
	Method Compare:Int(o1:Object,o2:Object) ' ****** these parameters are required **************
		Local f1:testFloat = testFloat(o1)
		Local f2:testFloat = testFloat(o2)
		Return Sgn(f2.flo - f1.flo)  '  this value you can change to whatever you want to compare but must return -1, 0 or 1.
	End

End

Class game Extends App
	Field mytest:ArrayList<testFloat> = New ArrayList<testFloat>

	Method OnCreate:Int()
		mytest.Comparator = New floatComparator    '<-------- pay attention here 
		mytest.AddLast(New testFloat(4.6))
		mytest.AddLast(New testFloat(4.7))
		mytest.AddLast(New testFloat(4.8))
		
		mytest.Sort()
		
		Print mytest.Get(0).flo + "  " + mytest.Get(1).flo + "  " + mytest.Get(2).flo

	End
End

Function Main:Int()
	Local g:game = New game
	Return 0
End



ondesic(Posted 2013) [#8]
Muddy_shoes
I'm wrong, you're right. Thanks.