Jump to content
Sign in to follow this  
james3mg

_LogicalSort.au3 include file

Recommended Posts

I finally got this UDF working (at least, as far as I've tested it, it works) :)

You can #include this file (it's small...there's only one function in the UDF, but you could Tidy it andget rid of my extensive commenting if you need smaller yet- I knew without it I'd never be able to re-create what I was doing), then call it with $_LogicalSort($_ls_list, [$_ls_start]) where $_ls_list is the list to sort (either a pipe-delimited (|) or single-dimensional array) and $_ls_start is the index to start from (no effect if $_ls_list is a string).

For instance, if you have this script:

#include <_LogicalSort>
dim $myArray[3]=["file1.txt","file100.txt","file2.txt"]
$myArray=_LogicalSort($myArray)oÝ÷ ÚØ^+­¬°Y[{Ýt÷

Edit: updated to new version of this UDF - now handles uppercase and lowercase better (see comments above function).

Old downloads: 16

_LogicalSort.au3

Edited by james3mg

"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110

Share this post


Link to post
Share on other sites

Is your code obfuscated? I asked Johnny 5 and The Terminator what it all means and they just scratched their heads! jk

Share this post


Link to post
Share on other sites

Is your code obfuscated? I asked Johnny 5 and The Terminator what it all means and they just scratched their heads! jk

^_^

Just tidy it to get rid of the comments - they make it look nasty - esp. in the forum. It looks OK in SciTE

It's not THAT bad, is it? :) :)

Edited by james3mg

"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110

Share this post


Link to post
Share on other sites

This is almost perfect, but it is still not exactly like Windows does it which is the way i prefer..... Could you maybe fix that??

Edited by TzarAlkex

Share this post


Link to post
Share on other sites

This is almost perfect, but it is still not exactly like Windows does it which is the way i prefer..... Could you maybe fix that??

Well, I'd say I'd see what I could do, but you'd have to tell me what you mean first - how does Windows do it? Can you give me a list that's sorted "my way" and the same list sorted "windows' way"? If you mean things being in a different order than you'd expect, understand that to not use the ASCII codes would require an array or string of ALL the possible characters be defined in the function, in order. ASCII seems cleaner to me - there aren't many characters in an odd order.

"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110

Share this post


Link to post
Share on other sites

Maybe I wants things to be to perfect and the sorting I was expected would be overkill but your function doesn't seem to sort specialcharacters (/\=-_ and others) at all.... (or atleast in a "non-logical" way....)

Check screenshots to see what i mean. (the first being explorer.exe and the second an array sorted with your function)

Posted ImagePosted Image

If you think it would be feasible for you to "fix" it that would be great ^_^ but if it's a "no-no" then plz forgive me for taking up your time :)

Share this post


Link to post
Share on other sites

Maybe I wants things to be to perfect and the sorting I was expected would be overkill but your function doesn't seem to sort specialcharacters (/\=-_ and others) at all.... (or atleast in a "non-logical" way....)

I appreciate you realizing that this might not be easy, given that my function is already written.

It does support the special characters - see the referenced "ASCII characters" of the AutoIt help file for the order in which they're sorted.

I understand that you want a different order however, so I tried making another function that called _ls_getIndex() instead of Asc() (using find and replace in scite), and defined a string in _ls_getIndex() that had all the characters on my keyboard in a more 'logical' order (symbols first, then numbers, then alternating uppercase and lowercase letters in order), and had it just return the value from StringInStr() of the character passed to it. It worked a little better, but was still sorting a little odd - I probably missed something as I only spent around 10 minutes on it. However, when I was comparing my output to your 'explorer' list, I noticed something odd. your list shows

a2.frank

a100.frank

-a100.frank

Clean template.frank

but I can't figure out why -a100.frank is ordered in the place it is. If it was reading it as a negative symbol, it should be 'smaller' and thus above all the "a" files. if it's a dash, I can't figure out why the order would go "a, -a, c". Would it follow that it would go

a2.frank

a100.frank

-a100.frank

Clean template.frank

-Clean template.frank

? No ordering of a custom list would give me a sorted list like that, without writing some extensive checks for the "-" character into the function itself. And if explorer does it with "-", then what other characters have special conditions like that? Also, in your list, I'd have expected exp.frank to come BEFORE exp2.frank, and DigitalClock.frank to come BEFORE DigitalClock2.frank, not the other way around! Wouldn't you expect punctuation (.) to come before numbers in explorer's sorting method? Same as " ", "-" and "="!!?

So I can't match your sorting, sorry. The long story short is that I just can't find a pattern in explorer's sorting method I could define and then emulate. :) I'll just have to stick with my ASCII sorting for now.

As a side note though, while working on your problem, I realized there's another odd condition using ASCII brings up - a list could feasably be sorted like:

A.txt

B.txt

Picture.txt

a_again.txt

b_again.txt

c_again.txt

picture2.txt

since in Ascii ALL capital letters come before ANY lowercase letters. I might have to modify the function to make everything it checks uppercase to avoid that condition. But that'll be a bit of rewriting as well, so until I have the dire need for it, I'm afraid I must advise you against holding your breath for it. ^_^ Edited by james3mg

"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110

Share this post


Link to post
Share on other sites

Thx for clearing (or darken :D) things....

Maybe we should ask Microsoft to sort using your method ;)

I understand that you want a different order however, so I tried making another function that called _ls_getIndex() instead of Asc() (using find and replace in scite), and defined a string in _ls_getIndex() that had all the characters on my keyboard in a more 'logical' order (symbols first, then numbers, then alternating uppercase and lowercase letters in order), and had it just return the value from StringInStr() of the character passed to it. It worked a little better, but was still sorting a little odd - I probably missed something as I only spent around 10 minutes on it.

Do you mind sharing that code if you have it left?? I think that (maybe) I could tweak it to get it to fit my needs.

Also, in your list, I'd have expected exp.frank to come BEFORE exp2.frank, and DigitalClock.frank to come BEFORE DigitalClock2.frank, not the other way around! Wouldn't you expect punctuation (.) to come before numbers in explorer's sorting method? Same as " ", "-" and "="!!?

I didn't even notice that... ;) But you are right it is strange :) :)

As a side note though, while working on your problem, I realized there's another odd condition using ASCII brings up - a list could feasably be sorted like:

since in Ascii ALL capital letters come before ANY lowercase letters. I might have to modify the function to make everything it checks uppercase to avoid that condition. But that'll be a bit of rewriting as well, so until I have the dire need for it, I'm afraid I must advise you against holding your breath for it. ;)

Correct me if I am wrong but I believe most file-operations (read,write,copy etc) is NOT case-sensitive, and therefore you could add a third option that when set runs StringLower() or something similar to provide a better (and maybe a little slower) sorting that could be used when case-sensitivity is of no concern ^_^

Share this post


Link to post
Share on other sites

Do you mind sharing that code if you have it left?? I think that (maybe) I could tweak it to get it to fit my needs.

No problem:

TO ALL OTHERS - NOTE THIS CODE DOES NOT WORK - I DON'T RECOMMEND IT!!!

#include-once
#cs                 about _LogicalSort2()
Script Author:      james3mg
AutoIt Version:     3.2.x and above (probably below as well, not tested)

Description:        Allows you to sort a list of text items 'logially' (ie similar to Win2000 and above's Explorer by default) so that
                    embedded numbers (especially multi-digit numbers) are read as numbers, rather than character-by-character.  That is,
                    resulting in a sorted list of file1.txt, file2.txt, file10.txt rather than file1.txt, file10.txt, file2.txt.
                    Uses ASCII codes for ordering, so may produce some 'illogical' results (ie { | and ~ are actually sorted AFTER
                    lowercase letters).  Refer to AutoIt Help's ASCII Characters section to see the order.

Parameters:         $_ls_list       the list to be sorted, either in a pipe (|)-delimited string, or in a single-dimensional array (required)
                    $_ls_start      the index number of a 0-based array to begin sorting from.  Usually 0 or 1.  Default is 0.  Useful for
                                    sorting arrays containing the number of elements in the array in [0], which should not be sorted.  No effect
                                    if $_ls_list is a string rather than an array.

Return values:
                    @error:     return value:       @extended:      meaning:
                    0           sorted array        ""              success
                    1           original list       ""              bad list - must be an array or pipe-delimited string
                    2           original list       ""              array has too many dimensions
                    3           original list       ""              no sorting to be done ($_ls_start too high, or too few elements in the list to be sorted)

Requirements:       None (relies almost exclusively on AutoIt functions UBound() and _ls_getIndex().
#ce
Func _LogicalSort2($_ls_list,$_ls_start=0)
#region initial setup and error checking
    Local $_ls_tmp, $_ls_tmp_array, $_ls_longestStrLen=0, $_ls_i, $_ls_n, $_ls_c, $_ls_row, $_ls_col
    If NOT IsArray($_ls_list) AND StringInStr($_ls_list,"|")=0 Then Return(SetError(1,"",$_ls_list));if the list isn't an array or pipe (|)-separated string, exit with an error code of 1
    If NOT IsArray($_ls_list) Then;if the list is a string, then
        $_ls_list=StringSplit($_ls_list,"|");split it at the pipes and make it an array
        For $_ls_i=1 To UBound($_ls_list)-1;for each element in the array
            $_ls_list[$_ls_i-1]=$_ls_list[$_ls_i];move all the numbers 'down' one array index, losing the number stored in [0]
        Next
        ReDim $_ls_list[UBound($_ls_list)-1];get rid of the extra index at the top (end) of the array
        $_ls_start=0;since this parameter has no effect on a string list, override anything they may have entered here so it starts sorting at element 0
    ElseIf UBound($_ls_list,0) <> 1 Then;elseif the array isn't one-dimensional, then
        Return(SetError(2,"",$_ls_list));exit with an error code of 2
    EndIf
    If UBound($_ls_list) <= 1 OR UBound($_ls_list)-1 <= $_ls_start Then Return(SetError(3,"",$_ls_list));if the array doesn't have two or more elements to sort, then exit with error code of 3 (there's no sorting to be done)
    ;ok, now the lists are valid, set up and ready to start sorting
#endregion initial setup and error checking
;here's how this works::
;Step 1: make a multi-dimensional array, with each 'row' being one of the list entries, and each column holding either one alpha character, or as many numbers as are consecutive.
;Step 2: go through the first column, starting with entry $_ls_start+1, comparing each entry with the one above it - if the (lower) entry has a smaller _ls_getIndex() code than the one above it, then move the whole row up and do it again, following the 'moving' element until it doesn't move any higher (correctly ordered or at $_ls_start), then move down to the next element and repeat
;Step 3: for each identical first column, run the sort again on the second column.
;Step 4: for each identical first and second column, run the sort again on the third column, and so on.
;Step 5: recompose each row into a single-dimensional array, and return the final array
#region Step 1
    ;first find the longest string:
    For $_ls_i=0 To UBound($_ls_list)-1;for each element in the array (even ones not being sorted)
        If StringLen($_ls_list[$_ls_i]) > $_ls_longestStrLen Then $_ls_longestStrLen=StringLen($_ls_list[$_ls_i]);if the length of the element is the longest one found yet, store the number in $_ls_longestStrLen
    Next
    ;now make the array that's one character per cell:
    Dim $_ls_tmp_array[UBound($_ls_list)][$_ls_longestStrLen];this array has enough rows to hold each list item, and enough columns to hold one character in each column per row
    For $_ls_i=0 To UBound($_ls_list)-1;for each element in the array
        $_ls_tmp=StringSplit($_ls_list[$_ls_i],"");split the list item into its characters
        For $_ls_n=1 To $_ls_tmp[0];for each character in the list item
            $_ls_tmp_array[$_ls_i][$_ls_n-1]=$_ls_tmp[$_ls_n];write it into its cell in $_ls_tmp_array
        Next
    Next
    ;now combine consecutice digits into a number string in a single cell:
    For $_ls_i=0 To UBound($_ls_tmp_array)-1;for each row (list item)
        For $_ls_n=0 To $_ls_longestStrLen-1;and each column within it
            If _ls_getIndex(0) < _ls_getIndex($_ls_tmp_array[$_ls_i][$_ls_n]) AND _ls_getIndex($_ls_tmp_array[$_ls_i][$_ls_n]) < _ls_getIndex(9) Then;if the character is a number, then
                If _ls_getIndex(0) < _ls_getIndex($_ls_tmp_array[$_ls_i][$_ls_n+1]) AND _ls_getIndex($_ls_tmp_array[$_ls_i][$_ls_n+1]) < _ls_getIndex(9) Then;if the next character is also a number, then
                    Do
                        $_ls_tmp_array[$_ls_i][$_ls_n]&=$_ls_tmp_array[$_ls_i][$_ls_n+1];combine the next number into the current cell
                        For $_ls_c=1 To $_ls_longestStrLen-2-$_ls_n;for each remaining character in the string
                            $_ls_tmp_array[$_ls_i][$_ls_n+$_ls_c]=$_ls_tmp_array[$_ls_i][$_ls_n+$_ls_c+1];shift it over one to fill the empty cell
                        Next
                        $_ls_tmp_array[$_ls_i][$_ls_longestStrLen-StringLen($_ls_tmp_array[$_ls_i][$_ls_n])+1]="";erase the latent character at the end of the string
                    Until NOT (_ls_getIndex(0) < _ls_getIndex($_ls_tmp_array[$_ls_i][$_ls_n+1]) AND _ls_getIndex($_ls_tmp_array[$_ls_i][$_ls_n+1]) < _ls_getIndex(9)) OR $_ls_tmp_array[$_ls_i][$_ls_n+1]="";until the next character isn't a number or the end of the string is reached.
                EndIf
                $_ls_tmp_array[$_ls_i][$_ls_n]=Number($_ls_tmp_array[$_ls_i][$_ls_n]);make the contents of the cell an actual number type, so IsNum() works
            EndIf
        Next
    Next
    ;_ArrayDisplay($_ls_tmp_array);check for Step 1 - needs array.au3 included.
#endregion Step 1
#region Steps 2-4
    For $_ls_col=0 To $_ls_longestStrLen-1;for every column (characters or number strings) in the rows,
        For $_ls_i=$_ls_start+1 To UBound($_ls_list)-1;and each sortable list item (row) with a sortable row above it (for comparing to),
            For $_ls_c=0 To $_ls_col-1;check every column leading up to the current one in the current row and the one above it
                If $_ls_tmp_array[$_ls_i][$_ls_c] <> $_ls_tmp_array[$_ls_i-1][$_ls_c] Then ContinueLoop 2;and if they're not equal at any point, move one row down and continue checking for identical leading cols - no sorting will be done on this one at this point.
            Next
            ;getting here means that sorting needs to run on this column-everything's equal leading up to it
            If (IsNumber($_ls_tmp_array[$_ls_i][$_ls_col]) AND NOT IsNumber($_ls_tmp_array[$_ls_i-1][$_ls_col]) AND _ls_getIndex(String(StringLeft($_ls_tmp_array[$_ls_i][$_ls_col],1))) < _ls_getIndex($_ls_tmp_array[$_ls_i-1][$_ls_col])) _ ;if the second cell is a number, the first isn't, and the first digit in the number has a smaller ascii code than the character,
            OR (NOT IsNumber($_ls_tmp_array[$_ls_i][$_ls_col]) AND IsNumber($_ls_tmp_array[$_ls_i-1][$_ls_col]) AND _ls_getIndex($_ls_tmp_array[$_ls_i][$_ls_col]) < _ls_getIndex(String(StringLeft($_ls_tmp_array[$_ls_i-1][$_ls_col],1)))) _;OR the second cell is a character, the first is a number, and the character's ascii code is smaller than the ascii code of the first digit in the number,
            OR (IsNumber($_ls_tmp_array[$_ls_i][$_ls_col]) AND IsNumber($_ls_tmp_array[$_ls_i-1][$_ls_col]) AND $_ls_tmp_array[$_ls_i][$_ls_col] < $_ls_tmp_array[$_ls_i-1][$_ls_col]) _ ;OR they're both numbers and the second is smaller than the first
            OR (NOT IsNumber($_ls_tmp_array[$_ls_i][$_ls_col]) AND NOT IsNumber($_ls_tmp_array[$_ls_i-1][$_ls_col]) AND _ls_getIndex($_ls_tmp_array[$_ls_i][$_ls_col]) < _ls_getIndex($_ls_tmp_array[$_ls_i-1][$_ls_col])) Then;OR they're both not numbers and the second has a smaller ascii code than the first, THEN
                ;ConsoleWrite($_ls_tmp_array[$_ls_i][$_ls_col] & " is smaller than " & $_ls_tmp_array[$_ls_i-1][$_ls_col]&@CRLF);for troubleshooting, I can uncomment this to watch the process in SciTE
                For $_ls_n=0 To $_ls_longestStrLen-1;move the smaller list item up, and the larger one down (switch their places) by:
                    $_ls_tmp=$_ls_tmp_array[$_ls_i-1][$_ls_n];1) store each col. of the larger list item
                    $_ls_tmp_array[$_ls_i-1][$_ls_n]=$_ls_tmp_array[$_ls_i][$_ls_n];2) replace each col. of the larger list item with the same col. of the smaller list item
                    $_ls_tmp_array[$_ls_i][$_ls_n]=$_ls_tmp;3) replace each col. of the original smaller list item with the same col of the larger list item (remembered in the temporary variable)
                Next
                $_ls_i-=2;make the loop keep stepping 'up' the list, one line at a time
                If $_ls_i<$_ls_start Then ContinueLoop 2;don't step 'up' the line so far that you start sorting rows that shouldn't be or exceed the dims of the array.
            EndIf
        Next
    Next
#endregion Steps 2-4
#region Step 5
    For $_ls_i=0 To UBound($_ls_list)-1;for every element in the list (sorted and un-sorted)
        $_ls_list[$_ls_i]="";clear out the listitem's text
        For $_ls_n=0 To $_ls_longestStrLen-1;for every character/number string in each row
            $_ls_list[$_ls_i]&=$_ls_tmp_array[$_ls_i][$_ls_n];add into the final list the next character/number string
        Next
    Next
    $_ls_tmp_array="";free memory-just in case
    Return(SetError(0,"",$_ls_list));exit sucessfully
#endregion Step 5
EndFunc

Func _ls_getIndex($_ls_indexChar,$_ls_useASCII=0)
    If $_ls_useASCII Then
        Return (Asc($_ls_indexChar))
    Else
        Local $_ls_sortStr=" ~!@#$%^&*()_+`=/*{}|[]\:;"&'"'&"'<>?,.1234567890Aa-BbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
        Return StringInStr($_ls_sortStr,$_ls_indexChar)
    EndIf
EndFunc

#include <array.au3>

Global $SortArray[22]=["-a100.frank","21","1a.frank","1b.frank","2a.frank","=a2.frank","a1.frank","a2.frank","a100.frank","Clean template.frank","DigitalClock.frank","DigitalClock2.frank","Empty template.frank","exp.frank","exp2.frank","FreeDriveSpace.frank","Notes.frank","Pagefile.frank","Ram.frank","RamPagefile.frank","SimpleMusic.frank","_a1.frank"]
_ArrayDisplay(_LogicalSort2($SortArray),@error)

Correct me if I am wrong but I believe most file-operations (read,write,copy etc) is NOT case-sensitive, and therefore you could add a third option that when set runs StringLower() or something similar to provide a better (and maybe a little slower) sorting that could be used when case-sensitivity is of no concern :)

See the first post - I've updated the file and it handles uppercase vs lowercase as you'd expect now (basically, before it checks the ASCII code of the character, it converts it to lowercase first, but doesn't change the case of the item in the final returned list...this has a side benefit of putting the characters [\]^_ and ` before any letters - the only common characters (those not in the extended ANSI set) that will be sorted after letters now are the characters {|} and ~

I hope this helps! Let me know of anything else you find, or if you find a better method for doing these types of sorting! ^_^


"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110

Share this post


Link to post
Share on other sites

Hi

I think this would be faster, but not sure about character set, case?

;_LogicalSortEx.au3
#include <array.au3>
;~ #include <arrayultdisplay.au3>
Local $a_Row, $myArray2D[6][3], $myArray[6] = ["afile1.txt", "afile100.txt", "afile2.txt", "file1.txt", "file100.txt", "file2.txt"  ]
For $i = 0 To UBound($myArray) - 1
    $arTemp1 = StringRegExp($myArray[$i], "(?:\D*)(\d*)", 1)
    If Not $arTemp1[0] Then $arTemp1[0] = 0
    $arTemp = StringRegExp($myArray[$i], "[\D]*", 1)
    If Not IsArray($arTemp) Then Local $arTemp[1] = [0]
    $myArray[$i] = $myArray[$i] & "|" & $arTemp1[0] & "|" & $arTemp[0]
Next
_ArrayDel1DFieldSortSt ($myArray, "3|2")
For $i = 0 To UBound($myArray) - 1
    $arTemp1 = StringRegExp($myArray[$i], "^[^\|]*", 1)
    If Not $arTemp1[0] Then $arTemp1[0] = 0
    $myArray[$i] = $arTemp1[0]
Next
_ArrayDisplay ($myArray)
;~ _ArrayultDisplay ($myArray)
Func _ArrayDel1DFieldSortSt(ByRef $arEither2D1D, $iIndex = "1"); 1D must be "|" delimited!
    Local $code = 'function SubSort( byref arSingle,iIndex)'
    $code &= @LF & '    arIndexN=split(iIndex,"|")'
    $code &= @LF & '    dim iAsc:iAsc=0'
    $code &= @LF & '    if arIndexN(0)<0 then iAsc=1'
    $code &= @LF & '    dim arIndex()'
    $code &= @LF & '    redim preserve arIndex(1)';:arIndex(1) =0
    $code &= @LF & '    for a= 0 to ubound(arIndexN)'
    $code &= @LF & '        arIndexN(a)=csng(arIndexN(a))'
    $code &= @LF & '        if arIndexN(a)<>"" and arIndexN(a)<>0 then'
    $code &= @LF & '            redim preserve arIndex(a)'
    $code &= @LF & '            arIndex(a)=abs(arIndexN(a))-1'
    $code &= @LF & '            arIndexN(a)=csng(Iif(arIndexN(a)<0,arIndexN(a)+1,arIndexN(a)-1))'
    $code &= @LF & '        End If'
    $code &= @LF & '    next'
    $code &= @LF & '    ArraySort arSingle, iAsc,  0, UBound(arSingle), arIndex(0)  ';SortArray, iAsc,First, Last,iViewColNum
    $code &= @LF & '    for indexcol=1 to ubound(arIndex)';col=2'; start with check on 2nd  index'; define first index as col 1 (in call, 1)
    $code &= @LF & '        SubSort1 arSingle,arIndex,indexcol,iif(arIndexN(indexcol)<0,-1,1)  ';->, sort order
;~  $code &= @LF & '        SubSort1 arSingle,arIndex,indexcol,(arIndex(indexcol)+1)/(arIndexN(indexcol)  ';->, sort order
    $code &= @LF & '    Next'
    $code &= @LF & '    SubSort=arSingle'
    $code &= @LF & 'end function   ';==>ArrayFieldSort
    $code &= @LF & 'function SubSort1(byref arArray,arIndex,indexcol, iAsc)'
    $code &= @LF & '    dim Row,col:col=arIndex(indexcol)'
    $code &= @LF & '    dim pcol:pcol=arIndex(indexcol-1)'
    $code &= @LF & '    iAsc=Iif(iAsc<0,1,0)'
    $code &= @LF & '    dim arTemp(),itemp, sMarker:sMarker="Equal"';,sTemp(1)
    $code &= @LF & '    redim preserve arTemp(1) ';redim extra row
    $code &= @LF & '    for Row=1 to UBound(arArray) '; go through all rows of 2d array in that column to check for dupes
    $code &= @LF & '            arRow=split(arArray(row),"|")'
    $code &= @LF & '            arRowB4=split(arArray(row-1),"|")'
    $code &= @LF & '        if indexcol>1 then ';check cols in each row first if more than 2 index cols
    $code &= @LF & '            for c=0 to indexcol-1'
    $code &= @LF & '                if arRow(arIndex(c))<>arRowB4(arIndex(c)) Then'
    $code &= @LF & '                    sMarker="pColsNotEqual"'
    $code &= @LF & '                    c=indexcol'
    $code &= @LF & '                End If'
    $code &= @LF & '            Next'
    $code &= @LF & '        End If'
    $code &= @LF & '        if arRow(pcol)=arRowB4(pcol) and sMarker="Equal" Then ';dupes in the prev col.
    $code &= @LF & '            arTemp(itemp)=arArray(row-1)';Array2DToD( arArray2d,"",0,row-1,1) '; set first line of new potential sort array
    $code &= @LF & '            redim preserve arTemp(itemp+1) ';redim extra row
    $code &= @LF & '            arTemp(itemp+1)=arArray(row)';Array2DToD( arArray2d,"",0,row-1,1) '; set first line of new potential sort array
    $code &= @LF & '            itemp=itemp+1'
    $code &= @LF & '        Else'
    $code &= @LF & '            sMarker="Equal"'
    $code &= @LF & '            SubSortDo1 arArray,arTemp,itemp,iAsc,col,row'
    $code &= @LF & '        End If'
    $code &= @LF & '    Next'
    $code &= @LF & '    SubSortDo1 arArray,arTemp,itemp,iAsc,col,row'
    $code &= @LF & 'end function   '
    $code &= @LF & 'function SubSortDo1(byref arArray,byref arTemp,byref itemp,iAsc,col,row)'
    $code &= @LF & '    dim sTemp()'
    $code &= @LF & '    if itemp>0 then'
    $code &= @LF & '        ArraySort arTemp,  iAsc,0, UBound(arTemp), col ';sort on current col (pcol+1), asc?
    $code &= @LF & '        for i= 0 to ubound(arTemp)'
    $code &= @LF & '            arArray(row-ubound(arTemp)+i-1)=arTemp(i)'
    $code &= @LF & '        Next'
    $code &= @LF & '    End If'
    $code &= @LF & '    redim preserve arTemp(1)'
    $code &= @LF & '    itemp=0'; change backto single, then get into 2d array properly, then go on to check next line'; row=row-1??
    $code &= @LF & '    SubSortDo1= SortArray'
    $code &= @LF & 'end function'
    $code &= @LF & 'Function IIf( expr, truepart, falsepart )'
    $code &= @LF & '   IIf = falsepart'
    $code &= @LF & '   If expr Then IIf = truepart'''
    $code &= @LF & 'End Function'
    $code &= @LF & 'function ArraySort(ByRef SortArray, iAsc,First, Last,iViewColNum)'
    $code &= @LF & '    dim strWrite,arCol,arColumn()'
    $code &= @LF & '    ReDim Preserve arColumn(ubound(SortArray))'
    $code &= @LF & '    Dim intPointer, booIsNumeric: booIsNumeric = True'
    $code &= @LF & '    For intPointer = First To Last'
    $code &= @LF & '        arCol = Split( SortArray(intPointer), "|", -1,0 )'
    $code &= @LF & '        If Not IsNumeric( arCol(iViewColNum) ) Then'
    $code &= @LF & '            booIsNumeric = False'
    $code &= @LF & '            Exit For'
    $code &= @LF & '        End If'
    $code &= @LF & '    Next'
    $code &= @LF & '    For intPointer = First To Last'
    $code &= @LF & '        arCol = Split( SortArray(intPointer), "|", -1,0 )'
    $code &= @LF & '            If booIsNumeric Then'
    $code &= @LF & '            arColumn(intPointer)  = CSng( arCol(iViewColNum) )'
    $code &= @LF & '        else'
    $code &= @LF & '            arColumn(intPointer)  =  arCol(iViewColNum)'
    $code &= @LF & '        End If'
    $code &= @LF & '    Next'
    $code &= @LF & '    QuickSortColumn  SortArray, arColumn,First, Last,iViewColNum '
    $code &= @LF & '    if iasc=1 then ReverseElements SortArray, 0, ubound(SortArray)'
    $code &= @LF & '    ArraySort= SortArray'
    $code &= @LF & 'End function   '
    $code &= @LF & 'function QuickSortColumn(ByRef SortArray, ByRef arColumn, First, Last,iViewColNum)'
    $code &= @LF & '    dim Low,High,collitem,arCol'
    $code &= @LF & '    dim Temp,ListSeparator'
    $code &= @LF & '    Low = First'
    $code &= @LF & '    High = Last'
    $code &= @LF & '    ListSeparator=arColumn((First + Last) / 2)'
    $code &= @LF & '    Do'
    $code &= @LF & '        While (arColumn(Low) < ListSeparator)'
    $code &= @LF & '            Low = Low + 1'
    $code &= @LF & '        WEnd'
    $code &= @LF & '        While (arColumn(High) > ListSeparator)'
    $code &= @LF & '            High = High - 1'
    $code &= @LF & '        WEnd'
    $code &= @LF & '        If (Low <= High) Then'
    $code &= @LF & '            Temp = SortArray(Low)'
    $code &= @LF & '            SortArray(Low) = SortArray(High)'
    $code &= @LF & '            SortArray(High) = Temp'
    $code &= @LF & '            Temp = arColumn(Low)'
    $code &= @LF & '            arColumn(Low) = arColumn(High)'
    $code &= @LF & '            arColumn(High) = Temp'
    $code &= @LF & '            Low = Low + 1'
    $code &= @LF & '            High = High - 1'
    $code &= @LF & '        End If'
    $code &= @LF & '    Loop While (Low <= High)'
    $code &= @LF & '    If (First < High) Then QuickSortColumn  SortArray, arColumn,First, High,iViewColNum '
    $code &= @LF & '    If (Low < Last) Then QuickSortColumn  SortArray, arColumn,Low, Last,iViewColNum '
    $code &= @LF & 'End function   '
    $code &= @LF & 'Sub ReverseElements( arrToReverse, intAlphaRow, intOmegaRow )'
    $code &= @LF & '    Dim intPointer, intUpper, intLower, varHolder'
    $code &= @LF & '    For intPointer = 0 To Int( (intOmegaRow - intAlphaRow) / 2 )'
    $code &= @LF & '        intUpper = intAlphaRow + intPointer'
    $code &= @LF & '        intLower = intOmegaRow - intPointer'
    $code &= @LF & '        varHolder = arrToReverse(intLower)'
    $code &= @LF & '        arrToReverse(intLower) = arrToReverse(intUpper)'
    $code &= @LF & '        arrToReverse(intUpper) = varHolder'
    $code &= @LF & '    Next'
    $code &= @LF & 'End Sub'
    Local $vbs = ObjCreate("ScriptControl")
    $vbs.language = "vbscript"
    $vbs.addcode($code)
    $arEither2D1D = $vbs.Run("SubSort", $arEither2D1D, $iIndex)
    $vbs = ""
EndFunc   ;==>_Array2D1DFieldSortSt
Best, Randall Edited by randallc

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×
×
  • Create New...