Sorting an array

BlitzMax Forums/BlitzMax Programming/Sorting an array

Hey Glenn, if you're still checking in on this...

Here's another example where an array of objects is sorted by two different properties of the objects. It's insanely fast compared to sorting a linked list, because this uses quicksort and doesn't repeatedly convert things back and forth the way overriding Compare() to ToString() would.

And it's a lot cleaner than my previous example. The basic method: Convert the objects to strings containing only the fields we want to sort followed by the original array index number, alphabetize that, and then read the ends of those strings to figure out in what order to put the new array of objects.

Lesson learned: Don't put anything into a TList unless you really need it to be a TList. When it comes to sorting, arrays and strings are your friends.

'  Sort_Resolutions
'
'  Returns a sorted version of the supplied array of
'  TResolution objects.  Each object represents a screen
'  resolution.  They have "width", "height", and "depth" fields,
'  and this sorts them by their area, breaking ties by depth.
'
'  This example code doesn't check for error conditions
'  (zero-length arrays) or bad data (fields containing tabs),
'  I removed that stuff to make this example concise.
'  Otherwise this is based on a chunk of an actual application.
'
Function Sort_Resolutions :TResolution[] ( old_list :TResolution[] )
	
	' width to which to pad out integers
	Const NUM_WIDTH   :Int    = 12
	' a character which should never occur in the data
	Const FIELD_SEP   :String = Chr(9)

	Local new_list    :TResolution[old_list.length] ' what we'll return
	Local string_list :String[old_list.length]      ' the data converted to strings
	Local i           :Int                          ' array index iterator
	Local parts       :String[]                     ' returned by Split()

	' Convert the records into strings.
	' The first field(s) are the info we want to sort on,
	' and the last field is the index of the original record.
	For i = 0 To old_list.length-1
		' field 0: area of screen
		' field 1: depth of screen
		' field 2: index of this record
		string_list[i] = ..
			RSet(old_list[i].width * old_list[i].height, NUM_WIDTH) + ..
			FIELD_SEP + RSet(old_list[i].depth, NUM_WIDTH) + ..
			FIELD_SEP + i
	Next ' i
	
	' Alphabetize the strings.
	string_list.Sort(True) ' True = ascending

	' Turn the strings back into records.
	' Last field of each string is the index of the record it came from.
	For i = 0 To string_list.length-1
		parts = string_list[i].Split(FIELD_SEP)
		new_list[i] = old_list[Int(parts[parts.length - 1])]
	Next ' i

	Return new_list
	
End Function ' _Sort_Resolutions