PDA

View Full Version : UDT Sort in thinBasic 1.10.5: AnyType, any field



ErosOlmi
15-10-2018, 23:12
thinBasic 1.10.5, among many other new features, introduced 2 new UDT concepts:
AnyType in script function parameter type
the possibility to specify UDT element names by a string expression calculated at run time using () notation

An example is better than many words.
The following script define 2 different UDT, creates 2 different UDT arrays, uses only one function (AnyUdt_QSort) to sort the 2 UDT array variables by different UDT field names.

9892


#MinVersion 1.10.5

uses "Console"

'---------------------------------------------------------
Type template1
'---------------------------------------------------------
'---Data
sName As Long
SValue As Word
sCount As Long

'---Fills in all the values at once!
function init(sName as long, sValue as word, sCount as long)
me.sName = sName
me.sValue = sValue
me.sCount = sCount
end function

'---Represents type as string
function to_string() as string
return strformat$("{1}{2}{3}{4}{5}", me.sName, $TAB, me.sValue, $TAB, me.sCount)
end function

End Type


'---------------------------------------------------------
Type template2
'---------------------------------------------------------
'---Data
sName As string * 20
sSurname As string * 20
lAge As Long

'---Fills in all the values at once!
function init(sName as string, sSurname as string, lAge as long)
me.sName = sName
me.sSurname = sSurname
me.lAge = lAge
end function

'---Represents type as string
function to_string() as string
return strformat$("{1}{2}{3}{4}{5}", me.sName, $TAB, me.sSurname, $TAB, me.lAge)
end function

End Type


'------------------------------------------------------------------------------
' Generic function used to sort any UDT by any UDT field name
' Function takes advance of
' - new pseudo type AnyUdt that means that UDT is determined at runtime
' - new feature that allows to determine UDT element name at runtime
' including its name between () after the point
'------------------------------------------------------------------------------
function AnyUdt_QSort(byref T() as AnyType, firstIndex as long, lastIndex as long, sFieldName as String)
local idxLow as long = firstIndex
local idxHigh as long = lastIndex
local idxMid as Long = (firstIndex + lastIndex) / 2


local lPos as Long = UDT_ElementByte(T(1).(sFieldName))
local lLen as Long = SizeOf(T(1).(sFieldName))




select case parse$(typeof(T(1).(sFieldName)), ".", 1)
case "String"
local sPivot as String = mid$(T(idxMid), lPos, lLen)


Repeat


While mid$(T(idxLow), lPos, lLen) < sPivot
idxLow += 1
Wend


While mid$(T(idxHigh), lPos, lLen) > sPivot
idxHigh -= 1
Wend

If idxLow <= idxHigh Then
SWAP T(idxLow), T(idxHigh)
idxLow += 1
idxHigh -= 1
End If

Until idxLow > idxHigh
case "Numeric"
local ePivot as ext = T(idxMid).(sFieldName)


Repeat


While T(idxLow).(sFieldName) < ePivot
idxLow += 1
Wend


While T(idxHigh).(sFieldName) > ePivot
idxHigh -= 1
Wend

If idxLow <= idxHigh Then
SWAP T(idxLow), T(idxHigh)
idxLow += 1
idxHigh -= 1
End If

Until idxLow > idxHigh
end Select

If firstIndex < idxHigh then
AnyUdt_QSort(T, firstIndex, idxHigh, sFieldName)
End If

If idxLow < lastIndex then
AnyUdt_QSort(T, idxLow, lastIndex, sFieldName)
End If

End function


'---------------------------------------------------------
printl "This script demonstrates the use of AnyType function parameter type"
printl "in conjunction with UDT dynamic element name using a string expression inside ()"
printl "for determining UDT element name."
printl "---"
printl "The same function, AnyUdt_QSort, will be used to sort 2 different UDT by different UDT field names"
printl "---"
'---------------------------------------------------------
printl "Press a key to continue" in %CCOLOR_FLIGHTRED
WaitKey


Dim i As Long
dim nElements as long = 10000
printl "Defining 2 different UDT arrays of", nElements," elements each"
Dim symbol1(nElements) As template1
Dim symbol2(nElements) As template2


printl "Filling each UDT element of the 2 UDT arrays ..."
randomize Timer
for i = 1 to nElements
symbol1(i).init(rnd(-10000, 10000), i, Rnd(1,1000))
symbol2(i).init("Name:" & format$(rnd(0, 9999),"0000"), "Surname:" & format$(i, "0000"), Rnd(1,100))
Next
printl "Done"




PrintL


String sSortByFieldName = "sCount"
printl "Start sorting first UDT by element whose name is", sSortByFieldName, Timer
AnyUdt_QSort(symbol1, 1, ubound(symbol1), sSortByFieldName)
printl "Done", Timer
printl "After Quick Sort", typeof(symbol1) + " by ." + sSortByFieldName
printl "First and last 5 elements:"
For i = 1 To nElements
'---Print first 5 elements
if i <= 5 Then
PrintL $TAB, symbol1(i).to_string()
end If
'---Print last 5 elements
if i >= nElements - 5 then
PrintL $TAB, symbol1(i).to_string()
end If

Next
PrintL


'[breakpoint] Quick Sort
sSortByFieldName = "sName"
printl "Start sorting second UDT by element whose name is", sSortByFieldName, Timer
AnyUdt_QSort(symbol2, 1, ubound(symbol2), sSortByFieldName)
printl "Done", Timer
printl "After Quick Sort", typeof(symbol2) + " by ." + sSortByFieldName
printl "First and last 5 elements:"
For i = 1 To nElements
'---Print first 5 elements
if i <= 5 Then
PrintL $TAB, symbol2(i).to_string()
end If
'---Print last 5 elements
if i >= nElements - 5 then
PrintL $TAB, symbol2(i).to_string()
end If
Next
printl


printl "All done. Press a key to end." in %CCOLOR_FLIGHTRED
WaitKey