I have an elementary problem, caused mostly from the lack of documentation in BlitzMax....
I am trying to sort an array of objects by a field. Here is a sample code:
SuperStrict
Type TCar
Field color:String
Field model:String
End Type
Local Car:TCar[100]
For Local n:Int = 0 To 99
Car[n] = New TCar
Select Rand(5)
Case 1 Car[n].color = "Red"
Case 2 Car[n].color = "Green"
Case 3 Car[n].color = "Blue"
Case 4 Car[n].color = "Purple"
Case 5 Car[n].color = "White"
End Select
Print Car[n].color
Next
Print "Sorting by color...."
Car.Sort() '<-- Obviously, this doesn't work...I need to specify the .color
For Local n:Int = 0 To 99
Print Car[n].color
Next
Am I using .sort() correctly?
SuperStrict
Type TCar
Field i_color:Int
Field color:String
Field model:String
Method SetColorByInt(i_c:Int)
i_color = i_c
Select i_color
Case 1 color = "Red"
Case 2 color = "Green"
Case 3 color = "Blue"
Case 4 color = "Purple"
Case 5 color = "White"
End Select
End Method
Function SortCarsByColor(A:TCar[])
Local swapped:Int = True, i:Int, j:TCar
While swapped
swapped = False
For i = 0 To A.length - 2
If A[i].i_color > A[i + 1].i_color Then
j = A[i]
'swap
A[i] = A[i + 1]
A[i + 1] = j
swapped = True
End If
Next
Wend
End Function
End Type
Local Car:TCar[100]
For Local n:Int = 0 To 99
Car[n] = New TCar
Car[n].SetColorByInt(Rand(5))
Next
Print "Sorting by color...."
TCar.SortCarsByColor(Car)
For Local n:Int = 0 To 99
Print Car[n].color + "~t" + Car[n].i_color
NextBubbleSort!
Method Compare:Int(withObject:Object)
Local other:TCar=TCar(withObject)
If other=Self Return 0
If other<>Null
Local clr1$=color.ToLower()
Local clr2$=other.color.ToLower()
For Local i:Int=0 To Min(clr1.length,clr2.length)-1
If clr1[i]=clr2[i] Continue
If clr1[i]>clr2[i] Return 1
Return -1
Next
If clr1.length=clr2.length Return 0
If clr1.length>clr2.length Return 1
Return -1
Else
Return 1
EndIf
End Method
Add this to TCar.
Look under Language->Objects for the documentation on the Compare method. I actually had no idea that Sort() was an array method until I saw that example.
Or something like this:
SuperStrict
Type TCar
Field color:String
Field model:String
Method Compare:Int(other:Object)
Local obj:TCar = TCar(other)
If obj = Self Return 0
If color > obj.color
Return 1
End If
Return -1
End Method
End Type
Local Car:TCar[100]
For Local n:Int = 0 To 99
Car[n] = New TCar
Select Rand(5)
Case 1 Car[n].color = "Red"
Case 2 Car[n].color = "Green"
Case 3 Car[n].color = "Blue"
Case 4 Car[n].color = "Purple"
Case 5 Car[n].color = "White"
End Select
Print Car[n].color
Next
Print "Sorting by color...."
Car.Sort() '<-- Obviously, this doesn't work...I need to specify the .color
For Local n:Int = 0 To 99
Print Car[n].color
Next
BUBBLE SORT IS EVIL. DO NOT USE IT.
It is slow and there are faster algorithms available that are still simple.
Doesn't array.Sort() use the bubblesort algorithm?
No, it uses Quicksort :-p
jsp: your example works just fine, but I don't understand what is going on! You never actually call the Compare method, so how does this work??
It's internal, the Sort method calls Compare to figure what's supposed to go where.
What Plash and Khomy Prime said.
From the docs:
Compare:Int( otherObject:Object )
Returns a value less than 0 if an object is less than another object,
a value greater than 0 if an object is greater than another object or
the value 0 if an object equals another object.
The compare method jsp provided is correct otherwise, but when color=obj.color it should either return 0 or compare another field. Not that it matters much with sorting, but things like this can cause annoying bugs later on.
Right, it's not that important for the sort here, but a good point as Tachyon may want to add a sub-sort on the TCar.model, depending on the output he is looking for. Returning 0 could also be faster in a huge array as you could save one swap in the quicksort, but i guess that's just minor.