<% '============================================================= '// '// 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 %>