;------------------------------------------------------------------------------------------------------------------------------------------ #DefineFunction udfItemListSortOrdinal (strItemList, strDelimiter, intDirection) If intDirection != @ASCENDING && intDirection != @DESCENDING Then intDirection = @ASCENDING If strItemList == "" Then Return "" intCount = ItemCount (strItemList, strDelimiter) If StrLen (strItemList) == intCount - 1 Then Return strItemList ; Get max item length, my sophisticated invention. intItemLenMax = 0 intBBSize = 1 + intCount + StrLen (strItemList) hdlBB = BinaryAlloc (intBBSize) BinaryPokeStr (hdlBB, 1, StrClean (strItemList, strDelimiter, " ", @TRUE, 2)) BinaryReplace (hdlBB, strDelimiter, @CRLF, @TRUE) BinaryPokeStr (hdlBB, intBBSize - 1, @CR) BinaryPokeStr (hdlBB, 0, @LF) strSearch = StrCat (@LF, @CR) While @TRUE BinaryReplace (hdlBB, strSearch, "", @TRUE) If BinaryEodGet (hdlBB) <= intItemLenMax Then Break intItemLenMax = intItemLenMax + 1 strSearch = StrCat (@LF, StrFill (" ", intItemLenMax), @CR) EndWhile hdlBB = BinaryFree (hdlBB) ; Ordinal sort, using BinarySort string sort with hex strings. intHigh = intCount - 1 intRecSize = intItemLenMax * 2 hdlBBSort = BinaryAlloc (intCount * intRecSize) For intI = 0 To intHigh strItem = ItemExtract (intI + 1, strItemList, strDelimiter) If strItem != "" Then BinaryPokeStr (hdlBBSort, intI * intRecSize, ChrStringToHex (strItem)) Next BinarySort (hdlBBSort, intRecSize, 0, intRecSize, @STRING | intDirection) strItemList = "" For intI = 0 To intHigh strItem = BinaryPeekStr (hdlBBSort, intI * intRecSize, intRecSize) If strItem != "" Then strItemList = StrCat (strItemList, strDelimiter, ChrHexToString (strItem)) Else strItemList = StrCat (strItemList, strDelimiter) Next hdlBBSort = BinaryFree (hdlBBSort) Return StrSub (strItemList, 2, -1) ;.......................................................................................................................................... ; This UDF "udfItemListSortOrdinal" sorts a list of alphanumerical values in ascending or descending direction ; and respects the ordinal character series. ; ; Ordinal means, that each byte of each string is binary compared "as is". ; Uppercase characters are placed before lowercase characters in standard ASCII order. ; ; Detlev Dalitz.20090513.20090515 ;.......................................................................................................................................... #EndFunction ;------------------------------------------------------------------------------------------------------------------------------------------ ;Test. strDelimiter = "," strAlphaNumList = "9A,AAp,Bu,BU,ba7,Apm,Ba2s,Zi,Or,1A" strResultList1 = udfItemListSortOrdinal (strAlphaNumList, strDelimiter, @ASCENDING) ; "1A,9A,AAp,Apm,BU,Ba2s,Bu,Or,Zi,ba7" strAlphaNumList = "," strResultList2 = udfItemListSortOrdinal (strAlphaNumList, strDelimiter, @ASCENDING) ; "," strAlphaNumList = ",," strResultList3 = udfItemListSortOrdinal (strAlphaNumList, strDelimiter, @ASCENDING) ; ",," strAlphaNumList = ",,,Bu,BU,ba7,,Ba2s,," strResultList4 = udfItemListSortOrdinal (strAlphaNumList, strDelimiter, @ASCENDING) ; ",,,,,,BU,Ba2s,Bu,ba7" strAlphaNumList = StrReplace (StrReplace (FileGet (IntControl (1004, 0, 0, 0, 0)), @CRLF, @LF), @CR, " "); We use this script as test input. strResultList = udfItemListSortOrdinal (strAlphaNumList, @LF, @ASCENDING) ClipPut (StrReplace (strResultList, @LF, @CRLF)) ; The result is now on the ClipBoard, you can paste it into any editor application. Exit ;========================================================================================================================================== ; Predecessor versions of UDF "udfItemListSortOrdinal". ;========================================================================================================================================== ; _6 200900515 String to hex conversion is now be handled by the functions ChrStringToHex and ChrHexToString. ; This gives about 5 pct. better performance than previous version _5. ; (I was not aware that those functions are already there!) ; This UDF has the best performance against the previous versions. ;.......................................................................................................................................... ; _5 200900513 "Get max item length" as "binary version" and "BinarySort". ; This is the current production version, same as stored in WinBatch Tech Data Base. ;.......................................................................................................................................... ; _4 200900512 "Get max item length" as "string version" and "BinarySort". ;.......................................................................................................................................... ; _3 200900512 "Get max item length" as "binary version" and "ItemListSort". ;.......................................................................................................................................... ; _2 200900512 "Get max item length" as "string version" and "ItemListSort". ;.......................................................................................................................................... ; _1 200900512 "Growing binary buffer" and "ItemListSort". ;.......................................................................................................................................... ; _0 200900512 This is my modified version of an initially introduced attempt by Jim Tailor. ; Topic: ItemSort Case Sensitive (7 of 25), Read 95 times ; Conf: WinBatch ; From: JimTaylor jtaylor@jtdata.com ; Date: Saturday, May 09, 2009 02:18 PM ;========================================================================================================================================== ; ;------------------------------------------------------------------------------------------------------------------------------------------ ; #DefineFunction udfItemListSortOrdinal_5 (strItemList, strDelimiter, intDirection) ; If intDirection != @ASCENDING && intDirection != @DESCENDING Then intDirection = @ASCENDING ; If strItemList == "" Then Return "" ; intCount = ItemCount (strItemList, strDelimiter) ; If StrLen (strItemList) == intCount - 1 Then Return strItemList ; ; ; Get max item length, my sophisticated invention. ; intItemLenMax = 0 ; intBBSize = 1 + intCount + StrLen (strItemList) ; hdlBB = BinaryAlloc (intBBSize) ; BinaryPokeStr (hdlBB, 1, StrClean (strItemList, strDelimiter, " ", @TRUE, 2)) ; BinaryReplace (hdlBB, strDelimiter, @CRLF, @TRUE) ; BinaryPokeStr (hdlBB, intBBSize - 1, @CR) ; BinaryPokeStr (hdlBB, 0, @LF) ; strSearch = StrCat (@LF, @CR) ; While @TRUE ; BinaryReplace (hdlBB, strSearch, "", @TRUE) ; If BinaryEodGet (hdlBB) <= intItemLenMax Then Break ; intItemLenMax = intItemLenMax + 1 ; strSearch = StrCat (@LF, StrFill (" ", intItemLenMax), @CR) ; EndWhile ; hdlBB = BinaryFree (hdlBB) ; ; ; Ordinal sort, using BinarySort string sort with hex strings. ; intHigh = intCount - 1 ; intRecSize = intItemLenMax * 2 ; hdlBB = BinaryAlloc (intItemLenMax) ; hdlBBSort = BinaryAlloc (intCount * intRecSize) ; For intI = 0 To intHigh ; strItem = ItemExtract (intI + 1, strItemList, strDelimiter) ; If strItem != "" Then BinaryPokeStr (hdlBBSort, intI * intRecSize, BinaryPeekHex (hdlBB, 0, BinaryPokeStr (hdlBB, 0, strItem))) ; Next ; BinarySort (hdlBBSort, intRecSize, 0, intRecSize, @STRING | intDirection) ; strItemList = "" ; For intI = 0 To intHigh ; strItem = BinaryPeekStr (hdlBBSort, intI * intRecSize, intRecSize) ; If strItem != "" Then strItemList = StrCat (strItemList, strDelimiter, BinaryPeekStr (hdlBB, 0, BinaryPokeHex (hdlBB, 0, strItem))) ; Else strItemList = StrCat (strItemList, strDelimiter) ; Next ; hdlBBSort = BinaryFree (hdlBBSort) ; hdlBB = BinaryFree (hdlBB) ; ; Return StrSub (strItemList, 2, -1) ; ;.......................................................................................................................................... ; ; This UDF "udfItemListSortOrdinal" sorts a list of alphanumerical values in ascending or descending direction ; ; and respects the ordinal character series. ; ; ; ; Ordinal means, that each byte of each string is binary compared "as is". ; ; Uppercase characters are placed before lowercase characters in standard ASCII order. ; ; ; ; Detlev Dalitz.20090513. ; ;.......................................................................................................................................... ; #EndFunction ;------------------------------------------------------------------------------------------------------------------------------------------ ; ; ;------------------------------------------------------------------------------------------------------------------------------------------ ; #DefineFunction udfItemListSortOrdinal_4 (strItemList, strDelimiter, intDirection) ; If intDirection != @ASCENDING && intDirection != @DESCENDING Then intDirection = @ASCENDING ; If strItemList == "" Then Return "" ; intCount = ItemCount (strItemList, strDelimiter) ; If StrLen (strItemList) == intCount - 1 Then Return strItemList ; ; ; Get max item length, my sophisticated invention. ; strTempList = StrCat (@LF, StrReplace (strItemList, strDelimiter, @CRLF), @CR) ; strTempList = StrClean (strTempList, @CRLF, " ", @TRUE, 2) ; intItemLenMax = 0 ; strSearch = StrCat (@LF, @CR) ; While @TRUE ; strTempList = StrReplace (strTempList, strSearch, "") ; If strTempList == "" Then Break ; intItemLenMax = intItemLenMax + 1 ; strSearch = StrCat (@LF, StrFill (" ", intItemLenMax), @CR) ; EndWhile ; ; ; Ordinal sort, using BinarySort string sort with hex strings. ; intHigh = intCount - 1 ; intRecSize = intItemLenMax * 2 ; hdlBB = BinaryAlloc (intItemLenMax) ; hdlBBSort = BinaryAlloc (intCount * intRecSize) ; For intI = 0 To intHigh ; strItem = ItemExtract (intI + 1, strItemList, strDelimiter) ; If strItem != "" Then BinaryPokeStr (hdlBBSort, intI * intRecSize, BinaryPeekHex (hdlBB, 0, BinaryPokeStr (hdlBB, 0, strItem))) ; Next ; BinarySort (hdlBBSort, intRecSize, 0, intRecSize, @STRING | intDirection) ; strItemList = "" ; For intI = 0 To intHigh ; strItem = BinaryPeekStr (hdlBBSort, intI * intRecSize, intRecSize) ; If strItem != "" Then strItemList = StrCat (strItemList, strDelimiter, BinaryPeekStr (hdlBB, 0, BinaryPokeHex (hdlBB, 0, strItem))) ; Else strItemList = StrCat (strItemList, strDelimiter) ; Next ; hdlBBSort = BinaryFree (hdlBBSort) ; hdlBB = BinaryFree (hdlBB) ; Return StrSub (strItemList, 2, -1) ; ;.......................................................................................................................................... ; ; This UDF "ItemListSortOrdinal" sorts a list of alphanumerical values in ascending or descending direction ; ; and respects the ordinal character series. ; ; ; ; Ordinal means, that each byte of each string is compared without linguistic interpretation. ; ; Uppercase characters are placed before lowercase characters. ; ; ; ; Detlev Dalitz.20090512. ; ;.......................................................................................................................................... ; #EndFunction ;------------------------------------------------------------------------------------------------------------------------------------------ ; ; ;------------------------------------------------------------------------------------------------------------------------------------------ ; #DefineFunction udfItemListSortOrdinal_3 (strItemList, strDelimiter) ; If strItemList == "" Then Return "" ; intCount = ItemCount (strItemList, strDelimiter) ; If StrLen (strItemList) == intCount - 1 Then Return strItemList ; ; ; Get max item length, my sophisticated invention. ; intItemLenMax = 0 ; strTempList = StrCat (@LF, StrReplace (strItemList, strDelimiter, @CRLF), @CR) ; intStrLen = StrLen (strTempList) ; hdlBB = BinaryAlloc (intStrLen) ; BinaryPokeStr (hdlBB, 0, strTempList) ; BinaryPokeStr (hdlBB, 0, StrClean (BinaryPeekStr (hdlBB, 0, BinaryEodGet (hdlBB) - 1), @CRLF, " ", @TRUE, 2)) ; strSearch = StrCat (@LF, @CR) ; While @TRUE ; BinaryReplace (hdlBB, strSearch, "", @TRUE) ; If BinaryEodGet (hdlBB) <= intItemLenMax Then Break ; intItemLenMax = intItemLenMax + 1 ; strSearch = StrCat (@LF, StrFill (" ", intItemLenMax), @CR) ; EndWhile ; hdlBB = BinaryFree (hdlBB) ; Drop (strTempList) ; ; ; Ordinal sort. ; hdlBB = BinaryAlloc (intItemLenMax) ; For intI = 1 To intCount ; strItem = ItemExtract (intI, strItemList, strDelimiter) ; If strItem != "" Then strItemList = ItemReplace (BinaryPeekHex (hdlBB, 0, BinaryPokeStr (hdlBB, 0, strItem)), intI, strItemList, strDelimiter) ; Next ; strItemList = ItemSort (strItemList, strDelimiter) ; For intI = 1 To intCount ; strItem = ItemExtract (intI, strItemList, strDelimiter) ; If strItem != "" Then strItemList = ItemReplace (BinaryPeekStr (hdlBB, 0, BinaryPokeHex (hdlBB, 0, strItem)), intI, strItemList, strDelimiter) ; Next ; hdlBB = BinaryFree (hdlBB) ; Return strItemList ; ;.......................................................................................................................................... ; ; This UDF "ItemListSortOrdinal" sorts a list of alphanumerical values in ascending direction ; ; and respects the ordinal character series. ; ; ; ; Ordinal means, that each byte of each string is compared without linguistic interpretation. ; ; Uppercase characters are placed before lowercase characters. ; ; ; ; Detlev Dalitz.20090512. ; ;.......................................................................................................................................... ; #EndFunction ;------------------------------------------------------------------------------------------------------------------------------------------ ; ; ;------------------------------------------------------------------------------------------------------------------------------------------ ; #DefineFunction udfItemListSortOrdinal_2 (strItemList, strDelimiter) ; If strItemList == "" Then Return "" ; intCount = ItemCount (strItemList, strDelimiter) ; If StrLen (strItemList) == intCount - 1 Then Return strItemList ; ; ; Get max item length, my sophisticated invention. ; strTempList = StrCat (@LF, StrReplace (strItemList, strDelimiter, @CRLF), @CR) ; strTempList = StrClean (strTempList, @CRLF, " ", @TRUE, 2) ; intItemLenMax = 0 ; strSearch = StrCat (@LF, @CR) ; While @TRUE ; strTempList = StrReplace (strTempList, strSearch, "") ; If strTempList == "" Then Break ; intItemLenMax = intItemLenMax + 1 ; strSearch = StrCat (@LF, StrFill (" ", intItemLenMax), @CR) ; EndWhile ; ; ; Ordinal sort. ; hdlBB = BinaryAlloc (intItemLenMax) ; For intI = 1 To intCount ; strItem = ItemExtract (intI, strItemList, strDelimiter) ; If strItem != "" Then strItemList = ItemReplace (BinaryPeekHex (hdlBB, 0, BinaryPokeStr (hdlBB, 0, strItem)), intI, strItemList, strDelimiter) ; Next ; strItemList = ItemSort (strItemList, strDelimiter) ; For intI = 1 To intCount ; strItem = ItemExtract (intI, strItemList, strDelimiter) ; If strItem != "" Then strItemList = ItemReplace (BinaryPeekStr (hdlBB, 0, BinaryPokeHex (hdlBB, 0, strItem)), intI, strItemList, strDelimiter) ; Next ; hdlBB = BinaryFree (hdlBB) ; Return strItemList ; ;.......................................................................................................................................... ; ; This UDF "ItemListSortOrdinal" sorts a list of alphanumerical values in ascending direction ; ; and respects the ordinal character series. ; ; ; ; Ordinal means, that each byte of each string is compared without linguistic interpretation. ; ; Uppercase characters are placed before lowercase characters. ; ; ; ; Detlev Dalitz.20090512. ; ;.......................................................................................................................................... ; #EndFunction ;------------------------------------------------------------------------------------------------------------------------------------------ ; ; ;------------------------------------------------------------------------------------------------------------------------------------------ ; #DefineFunction udfItemListSortOrdinal_1 (strItemList, strDelimiter) ; If strItemList == "" Then Return "" ; intCount = ItemCount (strItemList, strDelimiter) ; If StrLen (strItemList) == intCount - 1 Then Return strItemList ; intBBSizeMax = 0 ; hdlBB = 0 ; For intI = 1 To intCount ; strItem = ItemExtract (intI, strItemList, strDelimiter) ; If strItem != "" ; intBBSize = StrLen (strItem) ; If intBBSize > intBBSizeMax ; intBBSizeMax = intBBSize ; If hdlBB Then hdlBB = BinaryFree (hdlBB) ; EndIf ; If !hdlBB Then hdlBB = BinaryAlloc (intBBSizeMax) ; strItemList = ItemReplace (BinaryPeekHex (hdlBB, 0, BinaryPokeStr (hdlBB, 0, strItem)), intI, strItemList, strDelimiter) ; EndIf ; Next ; strItemList = ItemSort (strItemList, strDelimiter) ; For intI = 1 To intCount ; strItem = ItemExtract (intI, strItemList, strDelimiter) ; If strItem != "" Then strItemList = ItemReplace (BinaryPeekStr (hdlBB, 0, BinaryPokeHex (hdlBB, 0, strItem)), intI, strItemList, strDelimiter) ; Next ; If hdlBB Then hdlBB = BinaryFree (hdlBB) ; Return strItemList ; ;.......................................................................................................................................... ; ; This UDF "ItemListSortOrdinal" sorts a list of alphanumerical values in ascending direction ; ; and respects the ordinal character series. ; ; ; ; Ordinal means, that each byte of each string is compared without linguistic interpretation. ; ; Uppercase characters are placed before lowercase characters. ; ; ; ; Detlev Dalitz.20090512. ; ;.......................................................................................................................................... ; #EndFunction ;------------------------------------------------------------------------------------------------------------------------------------------ ; ; ;------------------------------------------------------------------------------------------------------------------------------------------ ; #DefineFunction udfItemListSortOrdinal_0 (strList, strDelimiter) ; If strList == "" Then Return "" ; intItemCount = ItemCount (strList, strDelimiter) ; strNumDelim = "|" ; strListNew = "" ; intEmpty = 0 ; For intI = 1 To intItemCount ; strItem = ItemExtract (intI, strList, strDelimiter) ; If strItem != "" ; intChrCount = StrLen (strItem) ; strChars = "" ; For intChr = 1 To intChrCount ; strChars = strChars : StrFixLeft (Char2Num (StrSub (strItem, intChr, 1)), "0", 3) : strNumDelim ; Next ; strListNew = strListNew : strChars : strDelimiter ; Else ; intEmpty = intEmpty + 1 ; EndIf ; Next ; strListNew = ItemSort (strListNew, strDelimiter) ; Trailing delimiter now leading. ; intItemCount = ItemCount (strListNew, strDelimiter) ; Just one item too much. ; strList = "" ; For intI = 2 To intItemCount ; Skip leading delimiter. ; strItem = ItemExtract (intI, strListNew, strDelimiter) ; intChrCount = ItemCount (strItem, strNumDelim) - 1 ; strChars = "" ; For intChr = 1 To intChrCount ; strChars = strChars : Num2Char (ItemExtract (intChr, strItem, strNumDelim)) ; Next ; strList = strList : strChars : strDelimiter ; Next ; If intEmpty Then strList = StrFill (strDelimiter, intEmpty) : strList ; Insert empty items as skipped above. ; strList = ItemRemove (-1, strList, strDelimiter) ; Return strList ; ;.......................................................................................................................................... ; ; This UDF "ItemListSortOrdinal" sorts a list of alphanumerical values in ascending or descending direction ; ; and respects the ordinal character series. ; ; ; ; Ordinal means, that each byte of each string is compared without linguistic interpretation. ; ; This UDF sorts uppercase characters before lowercase characters. ; ; ; ; Detlev Dalitz.20090512. ; ;.......................................................................................................................................... ; #EndFunction ;------------------------------------------------------------------------------------------------------------------------------------------ ; ; ;------------------------------------------------------------------------------------------------------------------------------------------ ; Topic: ItemSort Case Sensitive (7 of 25), Read 95 times ; Conf: WinBatch ; From: JimTaylor jtaylor@jtdata.com ; Date: Saturday, May 09, 2009 02:18 PM ; ; ; #DefineFunction ItemSortASCII(ilist,delimiter) ; ; If ilist == "" Then Return(ilist) ; If StrLen(delimiter) > 1 Then ; Message("Note","Delimiter must be one character.") ; Return("") ; EndIf ; ; icnt = ItemCount(ilist,delimiter) ; ntxt = "" ; nlist = "" ; For i = 1 To icnt ; itxt = ItemExtract(i,ilist,delimiter) ; If itxt == "" Then Continue ; For k = 1 To StrLen(itxt) ; ntxt = ntxt:StrFixLeft(Char2Num(StrSub(itxt,k,1)):"|","0",4) ; Next ; nlist = nlist:ItemRemove(-1,ntxt,"|"):delimiter ; ntxt = "" ; Next ; nlist = ItemRemove(-1,nlist,delimiter) ; nlist = ItemSort(nlist,delimiter) ; ; ntxt = "" ; ilist = "" ; For i = 1 To icnt ; itxt = ItemExtract(i,nlist,delimiter) ; kcnt = ItemCount(itxt,"|") ; For k = 1 To kcnt ; ; clipput(itxt:@CRLF:k:@CRLF:ItemExtract(k,itxt,"|")) ; ntxt = ntxt:Num2Char(ItemExtract(k,itxt,"|")) ; Next ; ilist = ilist:ntxt:delimiter ; ntxt = "" ; Next ; ilist = ItemRemove(-1,ilist,delimiter) ; ; Return (ilist) ; ; #EndFunction ;------------------------------------------------------------------------------------------------------------------------------------------ ;==========================================================================================================================================