Sorting function with callback
Posted: Mon Jun 26, 2017 2:05 am
Hi!
I think PureBasic could really use sorting functions that make use of a user-defined callback function to determine the sorting order.
The functions would look as follows:
They accept the list or array to be sorted and the address of the callback function as parameters.
The callback function would be defined as follows:
It accepts two pointers to the elements to be compared. It should return #True if *Greater is greater (belongs closer to the end of list) than *Lesser or #False otherwise. By passing pointers instead of values to the callback, it is possible to use the same sorting function for native-typed as well as structured lists.
One use for this function is to sort a list by multiple criteria, like it can be done in SQL with "ORDER BY a, b, c".
This code would sort People() by their year of graduation, and people with the same year of graduation would be sorted alphabetically by their names.
Another use is to sort a list by values that are not stored in the list elements themselves, but in other memory locations that are referenced by pointers inside the elements.
This code would sort the planes by their total thrust, which is the number of engines (stored in the Plane structure) multiplied by the thrust of a single engine (stored in the Engine structure, referenced by the Plane structure).
Furthermore it would be useful if the sorting function accepts a *CallbackData parameter that is passed to the callback, allowing to (re-)configure the callback for different tasks, preventing the need for many different callbacks for each task.
This would look as follows:
I hope my use cases demonstrate the usefulness of such sorting functions, so there is a chance they will be implemented.
Nils
I think PureBasic could really use sorting functions that make use of a user-defined callback function to determine the sorting order.
The functions would look as follows:
Code: Select all
SortArrayCallback(ArrayToSort(), @Callback())
SortListCallback(ListToSort(), @Callback())
The callback function would be defined as follows:
Code: Select all
Procedure.i Callback(*Greater, *Lesser)
EndProcedure
One use for this function is to sort a list by multiple criteria, like it can be done in SQL with "ORDER BY a, b, c".
Code: Select all
Structure People
Name.s
YearOfGraduation.i
EndStructure
NewList People.People()
AddElement(People())
People()\Name = "Bernard Einstein"
People()\YearOfGraduation = 1921
AddElement(People())
People()\Name = "Horst Schlämmer"
People()\YearOfGraduation = 1985
AddElement(People())
People()\Name = "Albert Einstein"
People()\YearOfGraduation = 1921
; Sort by year of graduation, sort people with same values by name
; like SQL "ORDER BY YearOfGraduation, Name"
Procedure Callback(*Greater.People, *Lesser.People)
If *Greater\YearOfGraduation > *Lesser\YearOfGraduation Or
(*Greater\YearOfGraduation = *Lesser\YearOfGraduation And *Greater\Name > *Lesser\Name)
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
SortListCallback(People(), @Callback())
Another use is to sort a list by values that are not stored in the list elements themselves, but in other memory locations that are referenced by pointers inside the elements.
Code: Select all
Structure Engine
Name.s
Thrust.d
EndStructure
Structure Plane
Name.s
*Engine.Engine
NumberOfEngines.i
EndStructure
; Engines
With Pratt.Engine
\Name = "Pratt & Whitney TF30-P-412A"
\Thrust = 68000
EndWith
With Tumanski.Engine
\Name = "Tumanski R-95Sh"
\Thrust = 40170
EndWith
; Planes
NewList Plane.Plane()
AddElement(Plane())
Plane()\Name = "Grumman F-14A"
Plane()\Engine = @Pratt
Plane()\NumberOfEngines = 2
AddElement(Plane())
Plane()\Name = "Sukhoi Su-25K"
Plane()\Engine = @Tumanski
Plane()\NumberOfEngines = 2
; Sort by total thrust
Procedure Callback(*Greater.Plane, *Lesser.Plane)
If (*Greater\Engine\Thrust * *Greater\NumberOfEngines) > (*Lesser\Engine\Thrust * *Lesser\NumberOfEngines)
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
SortListCallback(Plane(), @Callback())
Furthermore it would be useful if the sorting function accepts a *CallbackData parameter that is passed to the callback, allowing to (re-)configure the callback for different tasks, preventing the need for many different callbacks for each task.
This would look as follows:
Code: Select all
SortListCallback(ListToSort(), @Callback(), *CallbackData)
Procedure.i Callback(*Greater, *Lesser, *CallbackData)
EndProcedure
Nils