%
'=============================================================
'//
'// SortHelper
'//
'// version: 1.2
'// last modified: 11 Jul 2005 15:20 by Sasha Vukovic
'=============================================================
%>
<%
'--------------- Global Constants ----------------
'-------------------------------------------------
Class SortHelper
Private enumVERSION_SORT
Private enumSTRING_SORT
Private m_SortType
'-----------------------------------------------------------------------------------------------------------------
Private Sub SwapRows(ary,row1,row2)
'== This proc swaps two rows of an array
Dim x,tempvar
For x = 0 to Ubound(ary,1)
tempvar = ary(x,row1)
ary(x,row1) = ary(x,row2)
ary(x,row2) = tempvar
Next
End Sub
'------------------------------------------------------------------------------------------------------------------
Private Sub QuickSort( ByRef vec,loBound,hiBound,SortField)
'==--------------------------------------------------------==
'== Sort a 2 dimensional array on SortField ==
'== ==
'== This procedure is adapted from the algorithm given in: ==
'== ~ Data Abstractions & Structures using C++ by ~ ==
'== ~ Mark Headington and David Riley, pg. 586 ~ ==
'== Quicksort is the fastest array sorting routine for ==
'== unordered arrays. Its big O is n log n ==
'== ==
'== Parameters: ==
'== vec - array to be sorted ==
'== SortField - The field to sort on (2nd dimension value) ==
'== loBound and hiBound are simply the upper and lower ==
'== bounds of the array's 1st dimension. It's probably ==
'== easiest to use the LBound and UBound functions to ==
'== set these. ==
'==--------------------------------------------------------==
Dim pivot(),loSwap,hiSwap,temp,counter
Redim pivot (Ubound(vec,1))
'== Two items to sort
if hiBound - loBound = 1 then
if IsGreater( vec(SortField,loBound), vec(SortField,hiBound) ) then Call SwapRows(vec,hiBound,loBound)
End If
'== Three or more items to sort
For counter = 0 to Ubound(vec,1)
pivot(counter) = vec(counter,int((loBound + hiBound) / 2))
vec(counter,int((loBound + hiBound) / 2)) = vec(counter,loBound)
vec(counter,loBound) = pivot(counter)
Next
loSwap = loBound + 1
hiSwap = hiBound
do
'== Find the right loSwap
while loSwap < hiSwap and ( NOT IsGreater( vec(SortField,loSwap), pivot(SortField) ) )
loSwap = loSwap + 1
wend
'== Find the right hiSwap
while IsGreater ( vec(SortField,hiSwap), pivot(SortField) )
hiSwap = hiSwap - 1
wend
'== Swap values if loSwap is less then hiSwap
if loSwap < hiSwap then Call SwapRows(vec,loSwap,hiSwap)
loop while loSwap < hiSwap
For counter = 0 to Ubound(vec,1)
vec(counter,loBound) = vec(counter,hiSwap)
vec(counter,hiSwap) = pivot(counter)
Next
'== Recursively call function .. the beauty of Quicksort
'== 2 or more items in first section
if loBound < (hiSwap - 1) then Call QuickSort(vec,loBound,hiSwap-1,SortField)
'== 2 or more items in second section
if hiSwap + 1 < hibound then Call QuickSort(vec,hiSwap+1,hiBound,SortField)
End Sub
'------------------------------------------------------------------------------------------------------------------
Private Function IsGreater( ByRef sStringA, ByRef sStringB )
Select Case m_SortType
Case enumVERSION_SORT
IsGreater = IsGreaterForVersionSort( sStringA, sStringB )
Case enumSTRING_SORT
IsGreater = IsGreaterForStringSort( sStringA, sStringB )
End Select
End Function
'------------------------------------------------------------------------------------------------------------------
Private Function IsGreaterForStringSort( ByRef sStringA, ByRef sStringB )
IsGreaterForStringSort = Eval( sStringA > sStringB )
End Function
'------------------------------------------------------------------------------------------------------------------
Private Function IsGreaterForVersionSort( ByVal sStringA, ByVal sStringB )
Dim nMinLen, i, aCharsA, aCharsB, valA, valB
Dim DoLengthComparison
Const SEPARATOR = "."
IsGreaterForVersionSort = FALSE
DoLengthComparison = TRUE
' Replace other delimmiting symbols with dot
' This is used to sort version numbers.
sStringA = Replace( sStringA, "-", SEPARATOR)
sStringB = Replace( sStringB, "-", SEPARATOR)
sStringA = Replace( sStringA, "_", SEPARATOR)
sStringB = Replace( sStringB, "_", SEPARATOR)
' Split version string with dot separator
aCharsA = Split(sStringA, SEPARATOR)
aCharsB = Split(sStringB, SEPARATOR)
' Find which Ubound is smallest
nMinLen = UBound(aCharsA)
If nMinLen > UBound(aCharsB) Then nMinLen = UBound(aCharsB)
'Response.write "======================================================
"
'Response.write sStringA &" is greater then "& sStringB &"
"
' Content Comparison
For i = 0 To nMinLen
valA = aCharsA(i)
valB = aCharsB(i)
If IsNumeric(valA) AND IsNumeric(valB) Then
'Response.write valA &"IS NUMERIC"& valB &"
"
' Do number compare
valA = CDbl(valA)
valB = CDbl(valB)
If valA <> valB Then
DoLengthComparison = FALSE
If valA > valB Then
IsGreaterForVersionSort = TRUE
Exit For
Else
Exit For
End If
End If
Else
' Do string compare
If valA <> valB Then
DoLengthComparison = FALSE
If valA > valB Then
IsGreaterForVersionSort = TRUE
Exit For
Else
Exit For
End If
End If
End If
Next
' Continue with Lenght Comparison if required
If DoLengthComparison AND ( Len(sStringA) > Len(sStringB) ) Then
'Response.write "LENGTH COMPARISON
"
IsGreaterForVersionSort = TRUE
End If
'Response.write "RESULT is greater:"& IsGreaterForVersionSort &"
"
End Function
'-----------------------------------------------------------------------------------------------------------------
Public Sub VersionSort( ByRef vec, loBound, hiBound, SortField )
' Set default comparison implementation
m_SortType = enumVERSION_SORT
If hiBound >= 1 Then
' Run sorting
Call QuickSort( vec, loBound, hiBound, SortField)
End If
End Sub
'-----------------------------------------------------------------------------------------------------------------
Public Sub StringSort( ByRef vec, loBound, hiBound, SortField )
' Set default comparison implementation
m_SortType = enumSTRING_SORT
If hiBound >= 1 Then
' Run sorting
Call QuickSort( vec, loBound, hiBound, SortField)
End If
End Sub
'-----------------------------------------------------------------------------------------------------------------
Private Sub Class_Initialize()
' Set enums
enumVERSION_SORT = 1
enumSTRING_SORT = 2
End Sub
'-----------------------------------------------------------------------------------------------------------------
Private Sub Class_Terminate()
End Sub
'-----------------------------------------------------------------------------------------------------------------
End Class
%>