How to sort dictionary by object property vbscript - sorting

I am trying to sort a dictionary with a function that I found online by an object property which is the Id but on this For Each i In dict line I am getting this error message Microsoft VBScript runtime error: Object doesn't support this property or method. I have tried For Each i In dict.Items but I get the same error message with 'dict.Items' I am using a older version of VBScript so it does not have features like dict.Count
VBScript Class:
Class TestClass
Public ID
Public TestText
Private Sub Class_Initialize
TestText = ""
End Sub
End Class
Set gDic = CreateObject("Scripting.Dictionary")
For i = 1 to 5
Set temp = new TestClass
temp.ID = i
temp.TestText = "Test" & i
gDic.Add i,temp
Next
Set NewDic = SortDict(gDic)
msgbox NewDic.Items()(1).TestText
Sort function:
Function SortDict(ByVal dict)
Dim i, j, temp
For Each i In dict
For Each j In dict
If(dict.Item(i) <= dict.Item(j)) Then
temp = dict.Item(i)
dict.Item(i) = dict.Item(j)
dict.Item(j) = temp
End If
Next
Next
Set SortDict = dict
End Function

Try modifying your function to:
Function SortDict(dict)
Dim i, j, arrKeys, arrItems
arrKeys = dict.keys 'Array containing the keys
arrItems = dict.Items 'Array containing the Items(which are nothing but objects of class TestClass)
Set tempObj = New TestClass
For i=0 To UBound(arrItems)-1 'From 1st element to the penultimate element
For j=i+1 To UBound(arrItems) 'From i+1th element to last element
If arrItems(i).id < arrItems(j).id Then 'Sorting in DESCENDING ORDER by the Property "ID"
tempObj.ID = arrItems(i).ID
tempObj.TestText = arrItems(i).testText
dict.item(arrKeys(i)).ID = arrItems(j).ID
dict.item(arrKeys(i)).TestText = arrItems(j).TestText
dict.item(arrKeys(j)).ID = tempObj.ID
dict.item(arrKeys(j)).TestText = tempObj.TestText
End If
Next
Next
Set SortDict = dict
End Function
Before Sorting:
|Key |Value |
|----------------|---------------------|
|1 |1,Test1 |
|2 |2,Test2 |
|3 |3,Test3 |
|4 |4,Test4 |
|5 |5,Test5 |
After Sorting:
|Key |Value |
|----------------|---------------------|
|1 |5,Test5 |
|2 |4,Test4 |
|3 |3,Test3 |
|4 |2,Test2 |
|5 |1,Test1 |
I could not find a better way to swap the values. I am sure there is a better way to do that. Will update it once I get something.

To add onto the answers provided by #Potato, I needed to sort by descending two values in a dictionary and compare these values to a database. Luckily the UI allowed me to first sort by descending and then I used the Sorting method provided by #Potato to compare the values to the DB. I would have had to use more dictionaries if I were required to sort more than one value in the DB.
This function takes a dictionary a groups it by similar values such as ID. Then sorts that dictionary by a second value in ReverseSortDescDict(descDict)
Function OrderCompareDictionary(UICompareDict, MIPdict)
arrItems = UICompareDict.Items
arrKeys = UICompareDict.Keys
limitkeys = cint(UBound(arrKeys))
numOfCols = Ubound(arrItems(0))
Set descDict = CreateObject("Scripting.Dictionary")
For k = 0 To limitkeys
If Ubound(arrItems(k)) = numOfCols Then
If not (k < 0 or k > UBound(arrKeys)) Then
If not (k = UBound(arrKeys)) Then
If arrItems(k)(0) = arrItems(k + 1)(0) Then
descDict.Add arrKeys(k) , arrItems(k)
Else
descDict.Add arrKeys(k) , arrItems(k) 'Does not match next value
Call ReverseSortDescDict(descDict)
Call CompareAndResetDescDict(descDict, k, MIPdict)
End If
Else
If arrItems(k)(0) = arrItems(k - 1)(0) Then 'Last row matches previous row
descDict.Add arrKeys(k) , arrItems(k)
Call ReverseSortDescDict(descDict)
Call CompareAndResetDescDict(descDict, k, MIPdict)
Else
descDict.Add arrKeys(k) , arrItems(k)
Call ReverseSortDescDict(descDict)
Call CompareAndResetDescDict(descDict, k, MIPdict)
End If
End If
Else
MsgBox "Out of bounds for dictionary array values"
End If
Else
MsgBox "Error in comparison"
End If
Next
End Function
This function sorts by descending before comparing. Included print statements to see dictionary object.
Function ReverseSortDescDict(descDict)
Dim i, j, temp
For Each i In descDict
For Each j In descDict
If(descDict.Item(i)(1) >= descDict.Item(j)(1)) Then
temp = descDict.Item(i)
descDict.Item(i) = descDict.Item(j)
descDict.Item(j) = temp
End If
Next
Next
displayDescDictCount = 0
descDictKeys = descDict.Keys
descDictItems = descDict.Items
For each item in descDictItems
print descDictKeys (displayDescDictCount) & " " & item(0) & " " & item(1) & " " & item(2)
displayDescDictCount = displayDescDictCount + 1
Next
End Function

If you need to do a single pass along the dictionary you could use a disconnected recordset to sort the keys, then retrieve the values from the dictionary in the order to get the keys from the recordset.
dim rs 'the recordset used to sort keys must be global
Set D = CreateObject("Scripting.Dictionary")
for i=1 to 10
d.add right("0000"&Cint(rnd*10000),4), i
next
'
for each j in d.keys
wscript.echo j & " " & d(j)
next
wscript.echo ""
i=0
do
b= DicNextItem(d,i)
wscript.echo b(0)&" "&b(1)
loop until i=-1
'---------------------------------------------
Function DicNextItem(dic,i)
'returns successive items from dictionary ordered by keys
'arguments dic: the dictionary
' i: 0 must be passed at fist call,
' returns 1 if there are more items
' returns-1 if no more items
'returns array with the key in index 0 and the value and value in index 1
'requires rs as global variable (no static in vbs)
'it supposes the key is a string
const advarchar=200
const adopenstatic=3
dim a(2)
if i=0 then
Set rs = CreateObject("ADODB.RECORDSET")
with rs
.fields.append "Key", adVarChar, 100
.CursorType = adOpenStatic
.open
'add all keys to the disconnected recordset
for each i in Dic.keys
.AddNew
rs("Key").Value = i
.Update
next
.Sort= " Key ASC"
.MoveFirst
end with
i=1
end if
if rs.EOF then
a=array(nul,nul)
else
a(0)=rs(0)
a(1)=dic(a(0))
rs.movenext
end if
if rs.EOF then i=-1:set rs=nothing
DicNextItem=a
end function

I would load the dictionary data into a Collections.ArrayList which as a Sort option. If need it in a Dictionary then load it back once sorted.
' Load Dictionary with unsorted data
set oDic = CreateObject("Scripting.Dictionary")
oDic.add "5", "Test5"
oDic.add "3", "Test3"
oDic.add "4", "Test4"
oDic.add "1", "Test1"
oDic.add "2", "Test2"
' Create Collections.Arraylist and load with Dictionary data
dim list
Set list = CreateObject("System.Collections.ArrayList")
For Each obj in oDic.keys
'Msgbox "Key: " & obj & " Value: " & oDic(obj)
list.Add obj & "|" & oDic(obj)
Next
' Arraylist Sort/Reverse options
list.Sort
'list.Reverse 'Use this is want to reverse sort
'Clear Dictionary so can reload
oDic.RemoveAll
For i = 0 To list.Count - 1
a=Split(list.Item(i), "|")
oDic.add a(0), a(1)
Next
' Data now back in your dictionary if needs to be
For Each obj in oDic.keys
WScript.Echo "Key: " & obj & VbCrLf & "Value: " & oDic(obj)
Next

Related

Read a file's data within a specified range using VB script. Is it possible?

This is the middle of the code I'm trying to work with. Is there a way to make the file it's reading open and read from line 2 to line 97? Where I need the correction is starred (****). What I'm trying to do is get the data from lines 2 through 97 to compare to another file I'll have to open from the same lines. The beginning and ends of each file are different but the middle information should match thus I need these specific lines.
' Build Aliquot file name
strFile = aBarcodeExportDir & "A-" & yearStr & "-" & splitStr2(0) & ".csv"
'msgbox("open file: " & strFile)
If (objFS.FileExists(strFile)) Then
' Open A file
Set objFile = objFS.OpenTextFile(strFile)
' Build string with file name minus extension - used later to determine EOF
strFileNameNoExtension = "A-" & yearStr & "-" & splitStr2(0)
' Create dictionary to hold key/value pairs - key = position; value = barcode
Set dictA = CreateObject("Scripting.Dictionary")
' Begin processing A file
Do Until objFile.AtEndOfStream(*****)
' Read a line
strLine = objFile.ReadLine(*****)
' Split on semi-colons
splitStr = Split(strLine, ";")
' If splitStr array contains more than 1 element then continue
If(UBound(splitStr) > 0) Then
' If barcode field is equal to file name then EOF
If(splitStr(6) = strFileNameNoExtension) Then
' End of file - exit loop
Exit Do
Else
' Add to dictionary
' To calculate position
' A = element(2) = position in row (1-16)
compA = splitStr(2)
' B = element(4) = row
compB = splitStr(4)
' C = element(5.1) = number of max positions in row
splitElement5 = Split(splitStr(5), "/")
compC = splitElement5(0)
' position = C * (B - 1) + A
position = compC * (compB - 1) + compA
barcode = splitStr(6) & ";" & splitStr(0) & ";" & splitStr(1) & ";" & splitStr(2)
'msgbox(position & ":" & barcode)
' Add to dictionary
dictA.Add CStr(position), barcode
End If
End If
Loop
' Close A file
objFile.Close
To give the exact answer, we may have to look at your text files(I mean with all the split functions you are using). But, If you just want to compare lines 2-97 of two text files, you can get a hint from the following piece of code:
strPath1 = "C:\Users\gr.singh\Desktop\abc\file1.txt" 'Replace with your File1 Path
strPath2 = "C:\Users\gr.singh\Desktop\abc\file2.txt" 'Replace with your File2 Path
Set objFso = CreateObject("Scripting.FileSystemObject")
Set objFile1 = objFso.OpenTextFile(strPath1,1)
Set objFile2 = objFso.OpenTextFile(strPath2,1)
blnMatchFailed = False
Do Until objFile1.AtEndOfStream
If objFile1.Line=1 Then
objFile1.SkipLine() 'Skips the 1st line of both the files
objFile2.SkipLine()
ElseIf objFile1.Line>=2 And objFile1.Line<=97 Then
strFile1 = objFile1.ReadLine()
strFile2 = objFile2.ReadLine()
If StrComp(strFile1,strFile2,1)<>0 Then 'textual comparison. Change 1 to 0, if you want binary comparison of both lines
blnMatchFailed = True
intFailedLine = objFile1.Line
Exit Do 'As soon as match fails, exit the Do while Loop
Else
blnMatchFailed = False
End If
Else
Exit Do
End If
Loop
If blnMatchFailed Then
MsgBox "Comparison Failed at line "&intFailedLine
Else
MsgBox "Comparison Passed"
End If
objFile1.Close
objFile2.Close
Set objFile1 = Nothing
Set objFile2 = Nothing
Set objFso = Nothing

How to check the key is exists in collection or not

I want to check collection variable contains the key or not in visual basic 6.0
Below is the collection variable I am having
pcolFields As Collection
and I want to check whether it contains the field Event_Code. I am doing this as below but it not worked for me.
If IsMissing(pcolFields("Event_Code")) = False Then
'Do Something
End If
Here is an example solution with try-catch:
Private Function IsMissing(col As Collection, field As String)
On Error GoTo IsMissingError
Dim val As Variant
val = col(field)
IsMissing = False
Exit Function
IsMissingError:
IsMissing = True
End Function
Use it like this:
Private Sub Form_Load()
Dim x As New Collection
x.Add "val1", "key1"
Dim testkey As String
testkey = "key2"
If IsMissing(x, testkey) Then
Debug.Print "Key is Missing"
Else
Debug.Print "Val is " + x(testkey)
End If
Exit Sub
End Sub
You could also try a to Implement or Subclass the Collection and add a "has" Function
Collections are not useful if you need to check for existence, but they're useful for iteration. However, collections are sets of Variants and so are inherently slower than typed variables.
In nearly every case it's more useful (and more optimal) to use a typed array. If you need to have a keyed collection you should use the Dictionary object.
Some examples of general ways of using typed arrays:
Dim my_array() As Long ' Or whichever type you need
Dim my_array_size As Long
Dim index As Long
Dim position As Long
' Add new item (push)
ReDim Preserve my_array(my_array_size)
my_array(my_array_size) = 123456 ' something to add
my_array_size = my_array_size + 1
' Remove item (pop)
my_array_size = my_array_size - 1
If my_array_size > 0 Then
ReDim Preserve my_array(my_array_size - 1)
Else
Erase my_array
End If
' Remove item (any position)
position = 3 'item to remove
For index = position To my_array_size - 2
my_array(index) = my_array(index + 1)
Next
my_array_size = my_array_size - 1
ReDim Preserve my_array(my_array_size - 1)
' Insert item (any position)
ReDim Preserve my_array(my_array_size)
my_array_size = my_array_size + 1
For index = my_array_size - 1 To position + 1 Step -1
my_array(index) = my_array(index - 1)
Next
my_array(position) = 123456 ' something to insert
' Find item
For index = 0 To my_array_size - 1
If my_array(index) = 123456 Then
Exit For
End If
Next
If index < my_array_size Then
'found, position is in index
Else
'not found
End If
Whilst it may seem like a lot code. It is way faster. Intellisense will also work, which is a bonus. The only caveat is if you have very large data sets, then redim starts to get slow and you have to use slightly different techniques.
You can also use a Dictionary, be sure to include the Microsoft Scripting Runtime reference in your project:
Dim dict As New Dictionary
Dim value As Long
dict.Add "somekey", 123456
dict.Remove "somekey"
value = dict.Item("somekey")
If dict.Exists("somekey") Then
' found!
Else
' not found
End If
Dictionaries like collections just hold a bunch of Variants, so can hold objects etc.
We can check following code into vb.net code
If Collection.ContainsKey(KeyString) Then
'write code
End if
Collection is variable of Dictionary and KeyString is a key string which we need to find into collection
The method from efkah will fail if the Collection contains objects rather than primitive types. Here is a small adjustment:
'Test if a key is available in a collection
Public Function HasKey(coll As Collection, strKey As String) As Boolean
On Error GoTo IsMissingError
Dim val As Variant
' val = coll(strKey)
HasKey = IsObject(coll(strKey))
HasKey = True
On Error GoTo 0
Exit Function
IsMissingError:
HasKey = False
On Error GoTo 0
End Function

Asp Classic put the Sub in the function... Can i?

why now return ....Syntax error
Can i put the Sub rutine in the function? Or better way for this?!
Function SumerizePlanArrays(f_String, f_Type)
Set dic = CreateObject("Scripting.Dictionary")
Sub Add(s)
weight = Split(s,"$")(0)
values = Split(s,"$")(1)
pipes = Split(values, "|")
For Each line In pipes
val = Split(line, ",")
if f_Type = 1 then
dic(val(1)) = (dic(val(1))*weight/100) + CInt(val(2))
elseif f_Type = 2 then
dic(val(1)) = dic(val(1)) + CInt(val(2))
end if
Next
End Sub
arrString = Split(f_String,"#")
For i = 0 to UBound(arrString)
'wei = Split(arrString(i),"$")(0)
Add arrString(i)
Next
Set a = CreateObject("System.Collections.ArrayList")
For Each key In dic.Keys
a.Add "0," & key & "," & dic(key)
Next
a.Sort
result = Join(a.ToArray, "|")
SumerizePlanArrays = result
End Function
Microsoft VBScript compilation error '800a03ea'
Syntax error
/inc_func_projects.asp, line 2592
Sub Add(s)
^
No - you can't put a sub within a function, except in JavaScript or in the server side version called JScript. VBScript and JScript are two completely different languages, however.
You should be doing this...
Function SumerizePlanArrays(f_String, f_Type)
Set dic = CreateObject("Scripting.Dictionary")
arrString = Split(f_String,"#")
For i = 0 to UBound(arrString)
'NOTE: Updated the call to reflect comment by sadrasjd...
Add arrString(i, f_Type, dic)
Next
Set a = CreateObject("System.Collections.ArrayList")
For Each key In dic.Keys
a.Add "0," & key & "," & dic(key)
Next
a.Sort
result = Join(a.ToArray, "|")
SumerizePlanArrays = result
End Function
Sub Add(s, type, dic)
'NOTE: ^Updated the parameters to reflect comment by sadrasjd^
weight = Split(s,"$")(0)
values = Split(s,"$")(1)
pipes = Split(values, "|")
For Each line In pipes
val = Split(line, ",")
if type = 1 then
dic(val(1)) = (dic(val(1))*weight/100) + CInt(val(2))
elseif type = 2 then
dic(val(1)) = dic(val(1)) + CInt(val(2))
end if
Next
End Sub
NOTE: Updated the call to reflect the suggestion made by sadrasjd.

How to give a name to each list item in Visual Basic 6

I am making a music player using the list control. I want to let the user change the name of the song on the list, but i want some property of THAT list item to contain its path.
Please help me in this. Any kind of help will be appreciated. Thanks in advance.
EDIT
Private Sub AddToList(ByVal txtFileName As String)
Dim I As Integer
Dim blnFileAlreadyexists As Boolean
txtFileName = Trim(txtFileName)
If txtFileName <> "" Then
blnFileAlreadyexists = False
For I = 0 To List1.ListCount - 1
If Trim(List1.List(I)) = txtFileName Then
blnFileAlreadyexists = True
End If
Next
If Not blnFileAlreadyexists Then
List1.AddItem (txtFileName)
List1.ItemData (txtFileName)
End If
End If
End Sub
For a listbox, after you add an item set its x.itemdata(x.newindex) to the index of an array (or UDT array) that contains the corresponding data.
For a listview you can similarly use an individual items .Tag or .Key to store an array (or collection) index.
Linking a listbox example;
Option Explicit
Private Type TFileData
OriginalFilePath As String
ListBoxIndex As Integer
MoreBlaBla As String
'//any more members
End Type
Private maFiles() As TFileData
Private Sub Form_Load()
'//initial alloc
ReDim maFiles(0)
AddToList "AAAA"
AddToList "BBBB"
AddToList "AAAA"
AddToList "CCCC"
'//test by looping listbox;
Dim i As Integer
For i = 0 To List1.ListCount - 1
MsgBox List1.List(i) & " - " & maFiles(List1.ItemData(i)).OriginalFilePath
Next
'// a better type centric test;
For i = 0 To UBound(maFiles) - 1
MsgBox maFiles(i).OriginalFilePath & " - List entry: " & List1.List(maFiles(i).ListBoxIndex)
Next
End Sub
Private Sub AddToList(ByVal txtFileName As String)
Dim i As Integer
Dim blnFileAlreadyexists As Boolean
txtFileName = Trim(txtFileName)
If txtFileName <> "" Then
blnFileAlreadyexists = False
For i = 0 To List1.ListCount - 1
If Trim(List1.List(i)) = txtFileName Then
blnFileAlreadyexists = True
End If
Next
If Not blnFileAlreadyexists Then
'//add to list
List1.AddItem (txtFileName)
'//store the original value in the array;
maFiles(UBound(maFiles)).OriginalFilePath = "TEST: " & txtFileName
'//store the index of the array in the list;
List1.ItemData(List1.NewIndex) = UBound(maFiles)
'//or better store in the type
maFiles(UBound(maFiles)).ListBoxIndex = List1.NewIndex
'//increment the array for the next item;
ReDim Preserve maFiles(UBound(maFiles) + 1)
End If
End If
End Sub

How do I sort arrays using vbscript?

I'm scanning through a file looking for lines that match a certain regex pattern, and then I want to print out the lines that match but in alphabetical order. I'm sure this is trivial but vbscript isn't my background
my array is defined as
Dim lines(10000)
if that makes any difference, and I'm trying to execute my script from a normal cmd prompt
From microsoft
Sorting arrays in VBScript has never been easy; that’s because VBScript doesn’t have a sort command of any kind. In turn, that always meant that VBScript scripters were forced to write their own sort routines, be that a bubble sort routine, a heap sort, a quicksort, or some other type of sorting algorithm.
So (using .Net as it is installed on my pc):
Set outputLines = CreateObject("System.Collections.ArrayList")
'add lines
outputLines.Add output
outputLines.Add output
outputLines.Sort()
For Each outputLine in outputLines
stdout.WriteLine outputLine
Next
I know this is a pretty old topic but it might come in handy for anyone in the future. the script below does what the fella was trying to achieve purely using vbscript. when sorted terms starting in capital letters will have priority.
for a = UBound(ArrayOfTerms) - 1 To 0 Step -1
for j= 0 to a
if ArrayOfTerms(j)>ArrayOfTerms(j+1) then
temp=ArrayOfTerms(j+1)
ArrayOfTerms(j+1)=ArrayOfTerms(j)
ArrayOfTerms(j)=temp
end if
next
next
Disconnected recordsets can be useful.
Const adVarChar = 200 'the SQL datatype is varchar
'Create a disconnected recordset
Set rs = CreateObject("ADODB.RECORDSET")
rs.Fields.append "SortField", adVarChar, 25
rs.CursorType = adOpenStatic
rs.Open
rs.AddNew "SortField", "Some data"
rs.Update
rs.AddNew "SortField", "All data"
rs.Update
rs.Sort = "SortField"
rs.MoveFirst
Do Until rs.EOF
strList=strList & vbCrLf & rs.Fields("SortField")
rs.MoveNext
Loop
MsgBox strList
Here is a QuickSort that I wrote for the arrays returned from the GetRows method of ADODB.Recordset.
'Author: Eric Weilnau
'Date Written: 7/16/2003
'Description: QuickSortDataArray sorts a data array using the QuickSort algorithm.
' Its arguments are the data array to be sorted, the low and high
' bound of the data array, the integer index of the column by which the
' data array should be sorted, and the string "asc" or "desc" for the
' sort order.
'
Sub QuickSortDataArray(dataArray, loBound, hiBound, sortField, sortOrder)
Dim pivot(), loSwap, hiSwap, count
ReDim pivot(UBound(dataArray))
If hiBound - loBound = 1 Then
If (sortOrder = "asc" and dataArray(sortField,loBound) > dataArray(sortField,hiBound)) or (sortOrder = "desc" and dataArray(sortField,loBound) < dataArray(sortField,hiBound)) Then
Call SwapDataRows(dataArray, hiBound, loBound)
End If
End If
For count = 0 to UBound(dataArray)
pivot(count) = dataArray(count,int((loBound + hiBound) / 2))
dataArray(count,int((loBound + hiBound) / 2)) = dataArray(count,loBound)
dataArray(count,loBound) = pivot(count)
Next
loSwap = loBound + 1
hiSwap = hiBound
Do
Do While (sortOrder = "asc" and dataArray(sortField,loSwap) <= pivot(sortField)) or sortOrder = "desc" and (dataArray(sortField,loSwap) >= pivot(sortField))
loSwap = loSwap + 1
If loSwap > hiSwap Then
Exit Do
End If
Loop
Do While (sortOrder = "asc" and dataArray(sortField,hiSwap) > pivot(sortField)) or (sortOrder = "desc" and dataArray(sortField,hiSwap) < pivot(sortField))
hiSwap = hiSwap - 1
Loop
If loSwap < hiSwap Then
Call SwapDataRows(dataArray,loSwap,hiSwap)
End If
Loop While loSwap < hiSwap
For count = 0 to Ubound(dataArray)
dataArray(count,loBound) = dataArray(count,hiSwap)
dataArray(count,hiSwap) = pivot(count)
Next
If loBound < (hiSwap - 1) Then
Call QuickSortDataArray(dataArray, loBound, hiSwap-1, sortField, sortOrder)
End If
If (hiSwap + 1) < hiBound Then
Call QuickSortDataArray(dataArray, hiSwap+1, hiBound, sortField, sortOrder)
End If
End Sub
If you are going to output the lines anyway, you could run the output through the sort command. Not elegant, but it does not require much work:
cscript.exe //nologo YOUR-SCRIPT | Sort
Note //nologo omits the logo lines (Microsoft (R) Windows Script Host Version... blah blah blah) from appearing in the middle of your sorted output. (I guess MS does not know what stderr is for.)
See http://ss64.com/nt/sort.html for details on sort.
/+n is the most useful option if your sort key does not start in the first column.
Compares are always case-insensitive, which is lame.
Some old school array sorting. Of course this only sorts single dimension arrays.
'C:\DropBox\Automation\Libraries\Array.vbs
Option Explicit
Public Function Array_AdvancedBubbleSort(ByRef rarr_ArrayToSort(), ByVal rstr_SortOrder)
' ==================================================================================
' Date : 12/09/1999
' Author : Christopher J. Scharer (CJS)
' Description : Creates a sorted Array from a one dimensional array
' in Ascending (default) or Descending order based on the rstr_SortOrder.
' Variables :
' rarr_ArrayToSort() The array to sort and return.
' rstr_SortOrder The order to sort in, default ascending or D for descending.
' ==================================================================================
Const const_FUNCTION_NAME = "Array_AdvancedBubbleSort"
Dim bln_Sorted
Dim lng_Loop_01
Dim str_SortOrder
Dim str_Temp
bln_Sorted = False
str_SortOrder = Left(UCase(rstr_SortOrder), 1) 'We only need to know if the sort order is A(SENC) or D(ESEND)...and for that matter we really only need to know if it's D because we are defaulting to Ascending.
Do While (bln_Sorted = False)
bln_Sorted = True
str_Temp = ""
If (str_SortOrder = "D") Then
'Sort in descending order.
For lng_Loop_01 = LBound(rarr_ArrayToSort) To (UBound(rarr_ArrayToSort) - 1)
If (rarr_ArrayToSort(lng_Loop_01) < rarr_ArrayToSort(lng_Loop_01 + 1)) Then
bln_Sorted = False
str_Temp = rarr_ArrayToSort(lng_Loop_01)
rarr_ArrayToSort(lng_Loop_01) = rarr_ArrayToSort(lng_Loop_01 + 1)
rarr_ArrayToSort(lng_Loop_01 + 1) = str_Temp
End If
If (rarr_ArrayToSort((UBound(rarr_ArrayToSort) - 1) - (lng_Loop_01 - 1)) > rarr_ArrayToSort((UBound(rarr_ArrayToSort) - 1) - lng_Loop_01)) Then
bln_Sorted = False
str_Temp = rarr_ArrayToSort((UBound(rarr_ArrayToSort) - 1) - (lng_Loop_01 - 1))
rarr_ArrayToSort((UBound(rarr_ArrayToSort) - 1) - (lng_Loop_01 - 1)) = rarr_ArrayToSort((UBound(rarr_ArrayToSort) - 1) - lng_Loop_01)
rarr_ArrayToSort((UBound(rarr_ArrayToSort) - 1) - lng_Loop_01) = str_Temp
End If
Next
Else
'Default to Ascending.
For lng_Loop_01 = LBound(rarr_ArrayToSort) To (UBound(rarr_ArrayToSort) - 1)
If (rarr_ArrayToSort(lng_Loop_01) > rarr_ArrayToSort(lng_Loop_01 + 1)) Then
bln_Sorted = False
str_Temp = rarr_ArrayToSort(lng_Loop_01)
rarr_ArrayToSort(lng_Loop_01) = rarr_ArrayToSort(lng_Loop_01 + 1)
rarr_ArrayToSort(lng_Loop_01 + 1) = str_Temp
End If
If (rarr_ArrayToSort((UBound(rarr_ArrayToSort) - 1) - (lng_Loop_01 - 1)) < rarr_ArrayToSort((UBound(rarr_ArrayToSort) - 1) - lng_Loop_01)) Then
bln_Sorted = False
str_Temp = rarr_ArrayToSort((UBound(rarr_ArrayToSort) - 1) - (lng_Loop_01 - 1))
rarr_ArrayToSort((UBound(rarr_ArrayToSort) - 1) - (lng_Loop_01 - 1)) = rarr_ArrayToSort((UBound(rarr_ArrayToSort) - 1) - lng_Loop_01)
rarr_ArrayToSort((UBound(rarr_ArrayToSort) - 1) - lng_Loop_01) = str_Temp
End If
Next
End If
Loop
End Function
Public Function Array_BubbleSort(ByRef rarr_ArrayToSort())
' ==================================================================================
' Date : 03/18/2008
' Author : Christopher J. Scharer (CJS)
' Description : Sorts an array.
' ==================================================================================
Const const_FUNCTION_NAME = "Array_BubbleSort"
Dim lng_Loop_01
Dim lng_Loop_02
Dim var_Temp
For lng_Loop_01 = (UBound(rarr_ArrayToSort) - 1) To 0 Step -1
For lng_Loop_02 = 0 To lng_Loop_01
If rarr_ArrayToSort(lng_Loop_02) > rarr_ArrayToSort(lng_Loop_02 + 1) Then
var_Temp = rarr_ArrayToSort(lng_Loop_02 + 1)
rarr_ArrayToSort(lng_Loop_02 + 1) = rarr_ArrayToSort(lng_Loop_02)
rarr_ArrayToSort(lng_Loop_02) = var_Temp
End If
Next
Next
End Function
Public Function Array_GetDimensions(ByVal rarr_Array)
Const const_FUNCTION_NAME = "Array_GetDimensions"
Dim int_Dimensions
Dim int_Result
Dim str_Dimensions
int_Result = 0
If IsArray(rarr_Array) Then
On Error Resume Next
Do
int_Dimensions = -2
int_Dimensions = UBound(rarr_Array, int_Result + 1)
If int_Dimensions > -2 Then
int_Result = int_Result + 1
If int_Result = 1 Then
str_Dimensions = str_Dimensions & int_Dimensions
Else
str_Dimensions = str_Dimensions & ":" & int_Dimensions
End If
End If
Loop Until int_Dimensions = -2
On Error GoTo 0
End If
Array_GetDimensions = int_Result ' & ";" & str_Dimensions
End Function
Public Function Array_GetUniqueCombinations(ByVal rarr_Fields, ByRef robj_Combinations)
Const const_FUNCTION_NAME = "Array_GetUniqueCombinations"
Dim int_Element
Dim str_Combination
On Error Resume Next
Array_GetUniqueCombinations = CBool(False)
For int_Element = LBound(rarr_Fields) To UBound(rarr_Fields)
str_Combination = rarr_Fields(int_Element)
Call robj_Combinations.Add(robj_Combinations.Count & ":" & str_Combination, 0)
' Call Array_GetUniqueCombinationsSub(rarr_Fields, robj_Combinations, int_Element)
Next 'int_Element
For int_Element = LBound(rarr_Fields) To UBound(rarr_Fields)
Call Array_GetUniqueCombinationsSub(rarr_Fields, robj_Combinations, int_Element)
Next 'int_Element
Array_GetUniqueCombinations = CBool(True)
End Function 'Array_GetUniqueCombinations
Public Function Array_GetUniqueCombinationsSub(ByVal rarr_Fields, ByRef robj_Combinations, ByRef rint_LBound)
Const const_FUNCTION_NAME = "Array_GetUniqueCombinationsSub"
Dim int_Element
Dim str_Combination
On Error Resume Next
Array_GetUniqueCombinationsSub = CBool(False)
str_Combination = rarr_Fields(rint_LBound)
For int_Element = (rint_LBound + 1) To UBound(rarr_Fields)
str_Combination = str_Combination & "," & rarr_Fields(int_Element)
Call robj_Combinations.Add(robj_Combinations.Count & ":" & str_Combination, str_Combination)
Next 'int_Element
Array_GetUniqueCombinationsSub = CBool(True)
End Function 'Array_GetUniqueCombinationsSub
Public Function Array_HeapSort(ByRef rarr_ArrayToSort())
' ==================================================================================
' Date : 03/18/2008
' Author : Christopher J. Scharer (CJS)
' Description : Sorts an array.
' ==================================================================================
Const const_FUNCTION_NAME = "Array_HeapSort"
Dim lng_Loop_01
Dim var_Temp
Dim arr_Size
arr_Size = UBound(rarr_ArrayToSort) + 1
For lng_Loop_01 = ((arr_Size / 2) - 1) To 0 Step -1
Call Array_SiftDown(rarr_ArrayToSort, lng_Loop_01, arr_Size)
Next
For lng_Loop_01 = (arr_Size - 1) To 1 Step -1
var_Temp = rarr_ArrayToSort(0)
rarr_ArrayToSort(0) = rarr_ArrayToSort(lng_Loop_01)
rarr_ArrayToSort(lng_Loop_01) = var_Temp
Call Array_SiftDown(rarr_ArrayToSort, 0, (lng_Loop_01 - 1))
Next
End Function
Public Function Array_InsertionSort(ByRef rarr_ArrayToSort())
' ==================================================================================
' Date : 03/18/2008
' Author : Christopher J. Scharer (CJS)
' Description : Sorts an array.
' ==================================================================================
Const const_FUNCTION_NAME = "Array_InsertionSort"
Dim lng_ElementCount
Dim lng_Loop_01
Dim lng_Loop_02
Dim lng_Index
lng_ElementCount = UBound(rarr_ArrayToSort) + 1
For lng_Loop_01 = 1 To (lng_ElementCount - 1)
lng_Index = rarr_ArrayToSort(lng_Loop_01)
lng_Loop_02 = lng_Loop_01
Do While lng_Loop_02 > 0
If rarr_ArrayToSort(lng_Loop_02 - 1) > lng_Index Then
rarr_ArrayToSort(lng_Loop_02) = rarr_ArrayToSort(lng_Loop_02 - 1)
lng_Loop_02 = (lng_Loop_02 - 1)
End If
Loop
rarr_ArrayToSort(lng_Loop_02) = lng_Index
Next
End Function
Private Function Array_Merge(ByRef rarr_ArrayToSort(), ByRef rarr_ArrayTemp(), ByVal rlng_Left, ByVal rlng_MiddleIndex, ByVal rlng_Right)
' ==================================================================================
' Date : 03/18/2008
' Author : Christopher J. Scharer (CJS)
' Description : Merges an array.
' ==================================================================================
Const const_FUNCTION_NAME = "Array_Merge"
Dim lng_Loop_01
Dim lng_LeftEnd
Dim lng_ElementCount
Dim lng_TempPos
lng_LeftEnd = (rlng_MiddleIndex - 1)
lng_TempPos = rlng_Left
lng_ElementCount = (rlng_Right - rlng_Left + 1)
Do While (rlng_Left <= lng_LeftEnd) _
And (rlng_MiddleIndex <= rlng_Right)
If rarr_ArrayToSort(rlng_Left) <= rarr_ArrayToSort(rlng_MiddleIndex) Then
rarr_ArrayTemp(lng_TempPos) = rarr_ArrayToSort(rlng_Left)
lng_TempPos = (lng_TempPos + 1)
rlng_Left = (rlng_Left + 1)
Else
rarr_ArrayTemp(lng_TempPos) = rarr_ArrayToSort(rlng_MiddleIndex)
lng_TempPos = (lng_TempPos + 1)
rlng_MiddleIndex = (rlng_MiddleIndex + 1)
End If
Loop
Do While rlng_Left <= lng_LeftEnd
rarr_ArrayTemp(lng_TempPos) = rarr_ArrayToSort(rlng_Left)
rlng_Left = (rlng_Left + 1)
lng_TempPos = (lng_TempPos + 1)
Loop
Do While rlng_MiddleIndex <= rlng_Right
rarr_ArrayTemp(lng_TempPos) = rarr_ArrayToSort(rlng_MiddleIndex)
rlng_MiddleIndex = (rlng_MiddleIndex + 1)
lng_TempPos = (lng_TempPos + 1)
Loop
For lng_Loop_01 = 0 To (lng_ElementCount - 1)
rarr_ArrayToSort(rlng_Right) = rarr_ArrayTemp(rlng_Right)
rlng_Right = (rlng_Right - 1)
Next
End Function
Public Function Array_MergeSort(ByRef rarr_ArrayToSort(), ByRef rarr_ArrayTemp(), ByVal rlng_FirstIndex, ByVal rlng_LastIndex)
' ==================================================================================
' Date : 03/18/2008
' Author : Christopher J. Scharer (CJS)
' Description : Sorts an array.
' Note :The rarr_ArrayTemp array that is passed in has to be dimensionalized to the same size
' as the rarr_ArrayToSort array that is passed in prior to calling the function.
' Also the rlng_FirstIndex variable should be the value of the LBound(rarr_ArrayToSort)
' and the rlng_LastIndex variable should be the value of the UBound(rarr_ArrayToSort)
' ==================================================================================
Const const_FUNCTION_NAME = "Array_MergeSort"
Dim lng_MiddleIndex
If rlng_LastIndex > rlng_FirstIndex Then
' Recursively sort the two halves of the list.
lng_MiddleIndex = ((rlng_FirstIndex + rlng_LastIndex) / 2)
Call Array_MergeSort(rarr_ArrayToSort, rarr_ArrayTemp, rlng_FirstIndex, lng_MiddleIndex)
Call Array_MergeSort(rarr_ArrayToSort, rarr_ArrayTemp, lng_MiddleIndex + 1, rlng_LastIndex)
' Merge the results.
Call Array_Merge(rarr_ArrayToSort, rarr_ArrayTemp, rlng_FirstIndex, lng_MiddleIndex + 1, rlng_LastIndex)
End If
End Function
Public Function Array_Push(ByRef rarr_Array, ByVal rstr_Value, ByVal rstr_Delimiter)
Const const_FUNCTION_NAME = "Array_Push"
Dim int_Loop
Dim str_Array_01
Dim str_Array_02
'If there is no delimiter passed in then set the default delimiter equal to a comma.
If rstr_Delimiter = "" Then
rstr_Delimiter = ","
End If
'Check to see if the rarr_Array is actually an Array.
If IsArray(rarr_Array) = True Then
'Verify that the rarr_Array variable is only a one dimensional array.
If Array_GetDimensions(rarr_Array) <> 1 Then
Array_Push = "ERR, the rarr_Array variable passed in was not a one dimensional array."
Exit Function
End If
If IsArray(rstr_Value) = True Then
'Verify that the rstr_Value variable is is only a one dimensional array.
If Array_GetDimensions(rstr_Value) <> 1 Then
Array_Push = "ERR, the rstr_Value variable passed in was not a one dimensional array."
Exit Function
End If
str_Array_01 = Split(rarr_Array, rstr_Delimiter)
str_Array_02 = Split(rstr_Value, rstr_Delimiter)
rarr_Array = Join(str_Array_01 & rstr_Delimiter & str_Array_02)
Else
On Error Resume Next
ReDim Preserve rarr_Array(UBound(rarr_Array) + 1)
If Err.Number <> 0 Then ' "Subscript out of range" An array that was passed in must have been Erased to re-create it with new elements (possibly when passing an array to be populated into a recursive function)
ReDim rarr_Array(0)
Err.Clear
End If
If IsObject(rstr_Value) = True Then
Set rarr_Array(UBound(rarr_Array)) = rstr_Value
Else
rarr_Array(UBound(rarr_Array)) = rstr_Value
End If
End If
Else
'Check to see if the rstr_Value is an Array.
If IsArray(rstr_Value) = True Then
'Verify that the rstr_Value variable is is only a one dimensional array.
If Array_GetDimensions(rstr_Value) <> 1 Then
Array_Push = "ERR, the rstr_Value variable passed in was not a one dimensional array."
Exit Function
End If
rarr_Array = rstr_Value
Else
rarr_Array = Split(rstr_Value, rstr_Delimiter)
End If
End If
Array_Push = UBound(rarr_Array)
End Function
Public Function Array_QuickSort(ByRef rarr_ArrayToSort(), ByVal rlng_Low, ByVal rlng_High)
' ==================================================================================
' Date : 03/18/2008
' Author : Christopher J. Scharer (CJS)
' Description : Sorts an array.
' Note :The rlng_Low variable should be the value of the LBound(rarr_ArrayToSort)
' and the rlng_High variable should be the value of the UBound(rarr_ArrayToSort)
' ==================================================================================
Const const_FUNCTION_NAME = "Array_QuickSort"
Dim var_Pivot
Dim lng_Swap
Dim lng_Low
Dim lng_High
lng_Low = rlng_Low
lng_High = rlng_High
var_Pivot = rarr_ArrayToSort((rlng_Low + rlng_High) / 2)
Do While lng_Low <= lng_High
Do While (rarr_ArrayToSort(lng_Low) < var_Pivot _
And lng_Low < rlng_High)
lng_Low = lng_Low + 1
Loop
Do While (var_Pivot < rarr_ArrayToSort(lng_High) _
And lng_High > rlng_Low)
lng_High = (lng_High - 1)
Loop
If lng_Low <= lng_High Then
lng_Swap = rarr_ArrayToSort(lng_Low)
rarr_ArrayToSort(lng_Low) = rarr_ArrayToSort(lng_High)
rarr_ArrayToSort(lng_High) = lng_Swap
lng_Low = (lng_Low + 1)
lng_High = (lng_High - 1)
End If
Loop
If rlng_Low < lng_High Then
Call Array_QuickSort(rarr_ArrayToSort, rlng_Low, lng_High)
End If
If lng_Low < rlng_High Then
Call Array_QuickSort(rarr_ArrayToSort, lng_Low, rlng_High)
End If
End Function
Public Function Array_SelectionSort(ByRef rarr_ArrayToSort())
' ==================================================================================
' Date : 03/18/2008
' Author : Christopher J. Scharer (CJS)
' Description : Sorts an array.
' ==================================================================================
Const const_FUNCTION_NAME = "Array_SelectionSort"
Dim lng_ElementCount
Dim lng_Loop_01
Dim lng_Loop_02
Dim lng_Min
Dim var_Temp
lng_ElementCount = UBound(rarr_ArrayToSort) + 1
For lng_Loop_01 = 0 To (lng_ElementCount - 2)
lng_Min = lng_Loop_01
For lng_Loop_02 = (lng_Loop_01 + 1) To lng_ElementCount - 1
If rarr_ArrayToSort(lng_Loop_02) < rarr_ArrayToSort(lng_Min) Then
lng_Min = lng_Loop_02
End If
Next
var_Temp = rarr_ArrayToSort(lng_Loop_01)
rarr_ArrayToSort(lng_Loop_01) = rarr_ArrayToSort(lng_Min)
rarr_ArrayToSort(lng_Min) = var_Temp
Next
End Function
Public Function Array_ShellSort(ByRef rarr_ArrayToSort())
' ==================================================================================
' Date : 03/18/2008
' Author : Christopher J. Scharer (CJS)
' Description : Sorts an array.
' ==================================================================================
Const const_FUNCTION_NAME = "Array_ShellSort"
Dim lng_Loop_01
Dim var_Temp
Dim lng_Hold
Dim lng_HValue
lng_HValue = LBound(rarr_ArrayToSort)
Do
lng_HValue = (3 * lng_HValue + 1)
Loop Until lng_HValue > UBound(rarr_ArrayToSort)
Do
lng_HValue = (lng_HValue / 3)
For lng_Loop_01 = (lng_HValue + LBound(rarr_ArrayToSort)) To UBound(rarr_ArrayToSort)
var_Temp = rarr_ArrayToSort(lng_Loop_01)
lng_Hold = lng_Loop_01
Do While rarr_ArrayToSort(lng_Hold - lng_HValue) > var_Temp
rarr_ArrayToSort(lng_Hold) = rarr_ArrayToSort(lng_Hold - lng_HValue)
lng_Hold = (lng_Hold - lng_HValue)
If lng_Hold < lng_HValue Then
Exit Do
End If
Loop
rarr_ArrayToSort(lng_Hold) = var_Temp
Next
Loop Until lng_HValue = LBound(rarr_ArrayToSort)
End Function
Private Function Array_SiftDown(ByRef rarr_ArrayToSort(), ByVal rlng_Root, ByVal rlng_Bottom)
' ==================================================================================
' Date : 03/18/2008
' Author : Christopher J. Scharer (CJS)
' Description : Sifts the elements down in an array.
' ==================================================================================
Const const_FUNCTION_NAME = "Array_SiftDown"
Dim bln_Done
Dim max_Child
Dim var_Temp
bln_Done = False
Do While ((rlng_Root * 2) <= rlng_Bottom) _
And bln_Done = False
If rlng_Root * 2 = rlng_Bottom Then
max_Child = (rlng_Root * 2)
ElseIf rarr_ArrayToSort(rlng_Root * 2) > rarr_ArrayToSort(rlng_Root * 2 + 1) Then
max_Child = (rlng_Root * 2)
Else
max_Child = (rlng_Root * 2 + 1)
End If
If rarr_ArrayToSort(rlng_Root) < rarr_ArrayToSort(max_Child) Then
var_Temp = rarr_ArrayToSort(rlng_Root)
rarr_ArrayToSort(rlng_Root) = rarr_ArrayToSort(max_Child)
rarr_ArrayToSort(max_Child) = var_Temp
rlng_Root = max_Child
Else
bln_Done = True
End If
Loop
End Function
This is a vbscript implementation of merge sort.
'#Function Name: Sort
'#Author: Lewis Gordon
'#Creation Date: 4/26/12
'#Description: Sorts a given array either in ascending or descending order, as specified by the
' order parameter. This array is then returned at the end of the function.
'#Prerequisites: An array must be allocated and have all its values inputted.
'#Parameters:
' $ArrayToSort: This is the array that is being sorted.
' $Order: This is the sorting order that the array will be sorted in. This parameter
' can either be "ASC" or "DESC" or ascending and descending, respectively.
'#Notes: This uses merge sort under the hood. Also, this function has only been tested for
' integers and strings in the array. However, this should work for any data type that
' implements the greater than and less than comparators. This function also requires
' that the merge function is also present, as it is needed to complete the sort.
'#Examples:
' Dim i
' Dim TestArray(50)
' Randomize
' For i=0 to UBound(TestArray)
' TestArray(i) = Int((100 - 0 + 1) * Rnd + 0)
' Next
' MsgBox Join(Sort(TestArray, "DESC"))
'
'#Return value: This function returns a sorted array in the specified order.
'#Change History: None
'The merge function.
Public Function Merge(LeftArray, RightArray, Order)
'Declared variables
Dim FinalArray
Dim FinalArraySize
Dim i
Dim LArrayPosition
Dim RArrayPosition
'Variable initialization
LArrayPosition = 0
RArrayPosition = 0
'Calculate the expected size of the array based on the two smaller arrays.
FinalArraySize = UBound(LeftArray) + UBound(RightArray) + 1
ReDim FinalArray(FinalArraySize)
'This should go until we need to exit the function.
While True
'If we are done with all the values in the left array. Add the rest of the right array
'to the final array.
If LArrayPosition >= UBound(LeftArray)+1 Then
For i=RArrayPosition To UBound(RightArray)
FinalArray(LArrayPosition+i) = RightArray(i)
Next
Merge = FinalArray
Exit Function
'If we are done with all the values in the right array. Add the rest of the left array
'to the final array.
ElseIf RArrayPosition >= UBound(RightArray)+1 Then
For i=LArrayPosition To UBound(LeftArray)
FinalArray(i+RArrayPosition) = LeftArray(i)
Next
Merge = FinalArray
Exit Function
'For descending, if the current value of the left array is greater than the right array
'then add it to the final array. The position of the left array will then be incremented
'by one.
ElseIf LeftArray(LArrayPosition) > RightArray(RArrayPosition) And UCase(Order) = "DESC" Then
FinalArray(LArrayPosition+RArrayPosition) = LeftArray(LArrayPosition)
LArrayPosition = LArrayPosition + 1
'For ascending, if the current value of the left array is less than the right array
'then add it to the final array. The position of the left array will then be incremented
'by one.
ElseIf LeftArray(LArrayPosition) < RightArray(RArrayPosition) And UCase(Order) = "ASC" Then
FinalArray(LArrayPosition+RArrayPosition) = LeftArray(LArrayPosition)
LArrayPosition = LArrayPosition + 1
'For anything else that wasn't covered, add the current value of the right array to the
'final array.
Else
FinalArray(LArrayPosition+RArrayPosition) = RightArray(RArrayPosition)
RArrayPosition = RArrayPosition + 1
End If
Wend
End Function
'The main sort function.
Public Function Sort(ArrayToSort, Order)
'Variable declaration.
Dim i
Dim LeftArray
Dim Modifier
Dim RightArray
'Check to make sure the order parameter is okay.
If Not UCase(Order)="ASC" And Not UCase(Order)="DESC" Then
Exit Function
End If
'If the array is a singleton or 0 then it is sorted.
If UBound(ArrayToSort) <= 0 Then
Sort = ArrayToSort
Exit Function
End If
'Setting up the modifier to help us split the array effectively since the round
'functions aren't helpful in VBScript.
If UBound(ArrayToSort) Mod 2 = 0 Then
Modifier = 1
Else
Modifier = 0
End If
'Setup the arrays to about half the size of the main array.
ReDim LeftArray(Fix(UBound(ArrayToSort)/2))
ReDim RightArray(Fix(UBound(ArrayToSort)/2)-Modifier)
'Add the first half of the values to one array.
For i=0 To UBound(LeftArray)
LeftArray(i) = ArrayToSort(i)
Next
'Add the other half of the values to the other array.
For i=0 To UBound(RightArray)
RightArray(i) = ArrayToSort(i+Fix(UBound(ArrayToSort)/2)+1)
Next
'Merge the sorted arrays.
Sort = Merge(Sort(LeftArray, Order), Sort(RightArray, Order), Order)
End Function
Here's another vbscript implementation of quicksort. This is the in-place, unstable approach as defined in wikipedia (see here: http://en.wikipedia.org/wiki/Quicksort). Uses much less memory (original implementation requires upper and lower temporary storage arrays to be created upon every iteration, which can increase memory size by n terms in the worst case).
For ascending order, switch the signs.
If you want to sort characters, use Asc(ch) function.
'-------------------------------------
' quicksort
' Carlos Nunez, created: 25 April, 2010.
'
' NOTE: partition function also
' required
'-------------------------------------
function qsort(list, first, last)
Dim i, j
if (typeName(list) <> "Variant()" or ubound(list) = 0) then exit function 'list passed must be a collection or array.
'if the set size is less than 3, we can do a simple comparison sort.
if (last-first) < 3 then
for i = first to last
for j = first to last
if list(i) < list(j) then
swap list,i,j
end if
next
next
else
dim p_idx
'we need to set the pivot relative to the position of the subset currently being sorted.
'if the starting position of the subset is the first element of the whole set, then the pivot is the median of the subset.
'otherwise, the median is offset by the first position of the subset.
'-------------------------------------------------------------------------------------------------------------------------
if first-1 < 0 then
p_idx = round((last-first)/2,0)
else
p_idx = round(((first-1)+((last-first)/2)),0)
end if
dim p_nidx: p_nidx = partition(list, first, last, p_idx)
if p_nidx = -1 then exit function
qsort list, first, p_nidx-1
qsort list, p_nidx+1, last
end if
end function
function partition(list, first, last, idx)
Dim i
partition = -1
dim p_val: p_val = list(idx)
swap list,idx,last
dim swap_pos: swap_pos = first
for i = first to last-1
if list(i) <= p_val then
swap list,i,swap_pos
swap_pos = swap_pos + 1
end if
next
swap list,swap_pos,last
partition = swap_pos
end function
function swap(list,a_pos,b_pos)
dim tmp
tmp = list(a_pos)
list(a_pos) = list(b_pos)
list(b_pos) = tmp
end function
You either have to write your own sort by hand, or maybe try this technique:
http://www.aspfaqs.com/aspfaqs/ShowFAQ.asp?FAQID=83
You can freely intermix server side javascript with VBScript, so wherever VBScript falls short, switch to javascript.
VBScript does not have a method for sorting arrays so you've got two options:
Writing a sorting function like mergesort, from ground up.
Use the JScript tip from this article
When having large ("wide") arrays, instead of moving each element of a long row of data around, use a one-dimensional array with indexes of the array.
initialize ptr_arr with 0,1,2,3,..uBound(arr)
then access data with
arr(field_index,ptr_arr(row_index))
instead of
arr(field_index,row_index)
and just swap the elements of ptr_arr instead of swapping the rows.
If you are processing the array row by row, eg displaying it as a , you can take the lookout out of the inner loop:
max_col=uBound(arr,1)
response.write "<table>"
for n = 0 to uBound(arr,2)
response.write "<tr>"
row=ptr_arr(n)
for i=0 to max_col
response.write "<td>"&arr(i,row)&"</td>"
next
response.write "</tr>
next
response.write "</table>"
An old but still asked question. People posted links to this solution that are broken nowadays, so I post an example:
You can use ScriptControl to access JScript's array sort
You can provide your own jscript sorting function.
Unfortunateluy it works only in the 32 bit version of wsh...
a=split("this is a javascript array sort demo"," ")
wscript.echo vbcrlf & "alphabeticaly"&vbcrlf
a=sort(a)
for each i in a
wscript.echo i
next
wscript.echo vbcrlf & "by length"&vbcrlf
a=sortbylength(a)
for each i in a
wscript.echo i
next
function sort(a)
with createobject("ScriptControl")
.Language = "JScript"
.AddCode "function sortvbs(a) {return a.toArray().sort().join('\b')}"
sort= split(.Run("sortvbs",a),chr(8))
End With
end function
function sortbylength(a)
with createobject("ScriptControl")
.Language = "JScript"
.AddCode "function lensort(a,b){return((('' + a).length > ('' + b).length) ? 1 : ((('' + a).length < ('' + b).length) ? -1 : 0))}"
.Addcode "function sortvbs(a) {return a.toArray().sort(lensort).join('\b')}"
sortbylength= split(.Run("sortvbs",a),chr(8))
End With
end function
I actually just had to do something similar but with a 2D array yesterday. I am not that up to speed on vbscript and this process really bogged me down. I found that the articles here were very well written and got me on the road to sorting in vbscript.

Resources