dost0011 Posted January 8, 2010 Share Posted January 8, 2010 Hi, I took a really long time to find out, that _Arraysort() is doing something I really don't understand. I created a string: Filename & "Separation" & Size & "Separation" & DateoftheFile and wrote this string to an array. Ok, then I startet to sort the array and I couldn't believe it - the result is not depending from the Filename but from the DateoftheFile !!! Here is a very short example to show the problem: The first part is ok - and the second part is changing the order?!? #include <array.au3> DIM $array[2] $array[0] = "A" & chr(2); & "2" $array[1] = "A1" & chr(2); & "2" _ArraySort($array, 0, 0, 2) MsgBox(0,"1",$array[0]) MsgBox(0,"2",$array[1]) ;------------------------- $array[0] = "A" & chr(2) & "2" $array[1] = "A1" & chr(2) & "2" _ArraySort($array, 0, 0, 2) MsgBox(0,"1",$array[0]) MsgBox(0,"2",$array[1]) I tried the same with the faster ArrayIntroSort_1D - but it's the same. How can I sort the Arrays without the "Feature" that Number at the last is turning my result? Many thanks! Link to comment Share on other sites More sharing options...
PsaltyDS Posted January 8, 2010 Share Posted January 8, 2010 Yuck. That looks broke to me. I started to blame that on the non-printable delimiter (Chr(2) = [sTX]) but even with something like "xx" for a delimiter, the sort fails the exact same way: #include <array.au3> Dim $array[10] For $n = 0 To 9 If Mod($n, 2) Then ; Odd, add $n $array[$n] = "A" & $n & "xx" & "2" Else ; Even no $n $array[$n] = "A" & "xx" & "2" EndIf Next _ArrayDisplay($array, "BEFORE") _ArraySort($array, 0, 0, 2) _ArrayDisplay($array, "AFTER") Regardless of which way the compare wants to treat them, the strings "Axx2" should have been grouped together at the top or bottom of the array after sorting. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
Developers Jos Posted January 8, 2010 Developers Share Posted January 8, 2010 Regardless of which way the compare wants to treat them, the strings "Axx2" should have been grouped together at the top or bottom of the array after sorting. What about this version? #include <array.au3> Dim $array[10] For $n = 0 To 9 If Mod($n, 2) Then ; Odd, add $n $array[$n] = "A" & $n & "xx" & "2" Else ; Even no $n $array[$n] = "A" & "xx" & "2" EndIf Next _ArrayDisplay($array, "BEFORE") $x=_ArraySort($array) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $x = ' & $x & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console _ArrayDisplay($array, "AFTER") SciTE4AutoIt3 Full installer Download page - Beta files Read before posting How to post scriptsource Forum etiquette Forum Rules Live for the present, Dream of the future, Learn from the past. Link to comment Share on other sites More sharing options...
Developers Jos Posted January 8, 2010 Developers Share Posted January 8, 2010 (edited) Its StringCompare that looks not being consequent here.Dim $array[2] $array[0] = "A" & Chr(2); & "2" $array[1] = "A1" & Chr(2); & "2" ConsoleWrite(StringCompare($array[0], $array[1]) & @CRLF) ;------------------------- $array[0] = "A" & Chr(2) & "2" $array[1] = "A1" & Chr(2) & "2" ConsoleWrite(StringCompare($array[0], $array[1]) & @CRLF) Result:-1 1 Edited January 8, 2010 by Jos SciTE4AutoIt3 Full installer Download page - Beta files Read before posting How to post scriptsource Forum etiquette Forum Rules Live for the present, Dream of the future, Learn from the past. Link to comment Share on other sites More sharing options...
PsaltyDS Posted January 8, 2010 Share Posted January 8, 2010 (edited) <stupidity deleted> Edit: NVM, I don't believe I missed that parameter. Well, yes I do... Edited January 8, 2010 by PsaltyDS Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
Developers Jos Posted January 8, 2010 Developers Share Posted January 8, 2010 See the demo in my earlier post where several "Axx2" strings wind up sprinkled through the array instead of all at the top or all at the bottom together. Did you see my answer to that one? I think you made an error on the _ArraySort() statement. SciTE4AutoIt3 Full installer Download page - Beta files Read before posting How to post scriptsource Forum etiquette Forum Rules Live for the present, Dream of the future, Learn from the past. Link to comment Share on other sites More sharing options...
PsaltyDS Posted January 8, 2010 Share Posted January 8, 2010 (edited) Did you see my answer to that one? I think you made an error on the _ArraySort() statement. <hang head> <shuffle feet style='sheepishly'> Yeah... </shuffle> </hang> Still looks like the non-printing characters still throw it off: [0] = A1[STX]2 [1] = A[STX]2 [2] = A[STX]2 [3] = A[STX]2 [4] = A[STX]2 [5] = A[STX]2 [6] = A3[STX]2 [7] = A5[STX]2 [8] = A7[STX]2 [9] = A9[STX]2 But this is right if it treats non-printing characters as numeric strings i.e. String(ASC(Chr(2))), because that makes the result: [0] = A122 [1] = A22 [2] = A22 [3] = A22 [4] = A22 [5] = A22 [6] = A322 [7] = A522 [8] = A722 [9] = A922 Edit: That doesn't work either because with Chr(5) = [ENQ] it sorts exactly the same: [0] = A1[ENQ]2 [1] = A[ENQ]2 [2] = A[ENQ]2 [3] = A[ENQ]2 [4] = A[ENQ]2 [5] = A[ENQ]2 [6] = A3[ENQ]2 [7] = A5[ENQ]2 [8] = A7[ENQ]2 [9] = A9[ENQ]2 An actual "5" sorts as expected: [0] = A152 [1] = A352 [2] = A52 [3] = A52 [4] = A52 [5] = A52 [6] = A52 [7] = A552 [8] = A752 [9] = A952 Edited January 8, 2010 by PsaltyDS Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
Developers Jos Posted January 8, 2010 Developers Share Posted January 8, 2010 (edited) It looks like these characters are ignored. I haven't looked inside the source code yet but this seems to work: Dim $array[2] $array[0] = "A" & Chr(2); & "2" $array[1] = "A1" & Chr(2); & "2" ConsoleWrite(StringCompare($array[0], $array[1], 1) & @CRLF) ;------------------------- $array[0] = "A" & Chr(2) & "2" $array[1] = "A1" & Chr(2) & "2" ConsoleWrite(StringCompare($array[0], $array[1], 1) & @CRLF) Edited January 8, 2010 by Jos SciTE4AutoIt3 Full installer Download page - Beta files Read before posting How to post scriptsource Forum etiquette Forum Rules Live for the present, Dream of the future, Learn from the past. Link to comment Share on other sites More sharing options...
trancexx Posted January 8, 2010 Share Posted January 8, 2010 It looks like these characters are ignored. I haven't looked inside the source code yet but this seems to work: Dim $array[2] $array[0] = "A" & Chr(2); & "2" $array[1] = "A1" & Chr(2); & "2" ConsoleWrite(StringCompare($array[0], $array[1], 1) & @CRLF) ;------------------------- $array[0] = "A" & Chr(2) & "2" $array[1] = "A1" & Chr(2) & "2" ConsoleWrite(StringCompare($array[0], $array[1], 1) & @CRLF) This is interesting. I think default StringCompare (casesense param = 0) uses CompareStringW function to do the job. Seems like with LOCALE_SYSTEM_DEFAULT (0x400) passed as 'Locale' parameter and NORM_IGNORECASE (1) as 'CmpFlags' parameter. This doesn't follow the description in the help file btw. Help file says user's locale. With other two flags seems like custom written functions are used. Anyway, it's not about ignoring characters. Nothing is ignored. ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
dost0011 Posted January 12, 2010 Author Share Posted January 12, 2010 Hi guys, I couldn't follow you at all. Could you please explain what I can do to solve my problem? Is it a bug or not? Many thanks. Link to comment Share on other sites More sharing options...
trancexx Posted January 12, 2010 Share Posted January 12, 2010 Hi guys, I couldn't follow you at all. Could you please explain what I can do to solve my problem? Is it a bug or not? Many thanks. ;<- !Here!: expandcollapse popup;#include <array.au3> DIM $array[2] $array[0] = "A" & chr(2); & "2" $array[1] = "A1" & chr(2); & "2" _ArraySort($array, 0, 0, 2) MsgBox(0,"1",$array[0]) MsgBox(0,"2",$array[1]) ;------------------------- $array[0] = "A" & chr(2) & "2" $array[1] = "A1" & chr(2) & "2" _ArraySort($array, 0, 0, 2) MsgBox(0,"1",$array[0]) MsgBox(0,"2",$array[1]) ; #FUNCTION# ==================================================================================================================== ; Name...........: _ArraySort ; Description ...: Sort a 1D or 2D array on a specific index using the quicksort/insertionsort algorithms. ; Syntax.........: _ArraySort(ByRef $avArray[, $iDescending = 0[, $iStart = 0[, $iEnd = 0[, $iSubItem = 0]]]]) ; Parameters ....: $avArray - Array to sort ; $iDescending - [optional] If set to 1, sort descendingly ; $iStart - [optional] Index of array to start sorting at ; $iEnd - [optional] Index of array to stop sorting at ; $iSubItem - [optional] Sub-index to sort on in 2D arrays ; Return values .: Success - 1 ; Failure - 0, sets @error: ; |1 - $avArray is not an array ; |2 - $iStart is greater than $iEnd ; |3 - $iSubItem is greater than subitem count ; |4 - $avArray has too many dimensions ; Author ........: Jos van der Zande <jdeb at autoitscript dot com> ; Modified.......: LazyCoder - added $iSubItem option, Tylo - implemented stable QuickSort algo, Jos van der Zande - changed logic to correctly Sort arrays with mixed Values and Strings, Ultima - major optimization, code cleanup, removed $i_Dim parameter ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: Yes ; =============================================================================================================================== Func _ArraySort(ByRef $avArray, $iDescending = 0, $iStart = 0, $iEnd = 0, $iSubItem = 0) If Not IsArray($avArray) Then Return SetError(1, 0, 0) Local $iUBound = UBound($avArray) - 1 ; Bounds checking If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound If $iStart < 0 Then $iStart = 0 If $iStart > $iEnd Then Return SetError(2, 0, 0) ; Sort Switch UBound($avArray, 0) Case 1 __ArrayQuickSort1D($avArray, $iStart, $iEnd) If $iDescending Then _ArrayReverse($avArray, $iStart, $iEnd) Case 2 Local $iSubMax = UBound($avArray, 2) - 1 If $iSubItem > $iSubMax Then Return SetError(3, 0, 0) If $iDescending Then $iDescending = -1 Else $iDescending = 1 EndIf __ArrayQuickSort2D($avArray, $iDescending, $iStart, $iEnd, $iSubItem, $iSubMax) Case Else Return SetError(4, 0, 0) EndSwitch Return 1 EndFunc ;==>_ArraySort ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __ArrayQuickSort1D ; Description ...: Helper function for sorting 1D arrays ; Syntax.........: __ArrayQuickSort1D(ByRef $avArray, ByRef $iStart, ByRef $iEnd) ; Parameters ....: $avArray - Array to sort ; $iStart - Index of array to start sorting at ; $iEnd - Index of array to stop sorting at ; Return values .: None ; Author ........: Jos van der Zande, LazyCoder, Tylo, Ultima ; Modified.......: ; Remarks .......: For Internal Use Only ; Related .......: ; Link ..........: ; Example .......: ; =============================================================================================================================== Func __ArrayQuickSort1D(ByRef $avArray, ByRef $iStart, ByRef $iEnd) If $iEnd <= $iStart Then Return Local $vTmp ; InsertionSort (faster for smaller segments) If ($iEnd - $iStart) < 15 Then Local $vCur For $i = $iStart + 1 To $iEnd $vTmp = $avArray[$i] If IsNumber($vTmp) Then For $j = $i - 1 To $iStart Step -1 $vCur = $avArray[$j] ; If $vTmp >= $vCur Then ExitLoop If ($vTmp >= $vCur And IsNumber($vCur)) Or (Not IsNumber($vCur) And StringCompare($vTmp, $vCur) >= 0) Then ExitLoop $avArray[$j + 1] = $vCur Next Else For $j = $i - 1 To $iStart Step -1 If (StringCompare($vTmp, $avArray[$j], 2) >= 0) Then ExitLoop ;<- !Here! $avArray[$j + 1] = $avArray[$j] Next EndIf $avArray[$j + 1] = $vTmp Next Return EndIf ; QuickSort Local $L = $iStart, $R = $iEnd, $vPivot = $avArray[Int(($iStart + $iEnd) / 2)], $fNum = IsNumber($vPivot) Do If $fNum Then ; While $avArray[$L] < $vPivot While ($avArray[$L] < $vPivot And IsNumber($avArray[$L])) Or (Not IsNumber($avArray[$L]) And StringCompare($avArray[$L], $vPivot) < 0) $L += 1 WEnd ; While $avArray[$R] > $vPivot While ($avArray[$R] > $vPivot And IsNumber($avArray[$R])) Or (Not IsNumber($avArray[$R]) And StringCompare($avArray[$R], $vPivot) > 0) $R -= 1 WEnd Else While (StringCompare($avArray[$L], $vPivot) < 0) $L += 1 WEnd While (StringCompare($avArray[$R], $vPivot) > 0) $R -= 1 WEnd EndIf ; Swap If $L <= $R Then $vTmp = $avArray[$L] $avArray[$L] = $avArray[$R] $avArray[$R] = $vTmp $L += 1 $R -= 1 EndIf Until $L > $R __ArrayQuickSort1D($avArray, $iStart, $R) __ArrayQuickSort1D($avArray, $L, $iEnd) EndFunc ;==>__ArrayQuickSort1D ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __ArrayQuickSort2D ; Description ...: Helper function for sorting 2D arrays ; Syntax.........: __ArrayQuickSort2D(ByRef $avArray, ByRef $iStep, ByRef $iStart, ByRef $iEnd, ByRef $iSubItem, ByRef $iSubMax) ; Parameters ....: $avArray - Array to sort ; $iStep - Step size (should be 1 to sort ascending, -1 to sort descending!) ; $iStart - Index of array to start sorting at ; $iEnd - Index of array to stop sorting at ; $iSubItem - Sub-index to sort on in 2D arrays ; $iSubMax - Maximum sub-index that array has ; Return values .: None ; Author ........: Jos van der Zande, LazyCoder, Tylo, Ultima ; Modified.......: ; Remarks .......: For Internal Use Only ; Related .......: ; Link ..........: ; Example .......: ; =============================================================================================================================== Func __ArrayQuickSort2D(ByRef $avArray, ByRef $iStep, ByRef $iStart, ByRef $iEnd, ByRef $iSubItem, ByRef $iSubMax) If $iEnd <= $iStart Then Return ; QuickSort Local $vTmp, $L = $iStart, $R = $iEnd, $vPivot = $avArray[Int(($iStart + $iEnd) / 2)][$iSubItem], $fNum = IsNumber($vPivot) Do If $fNum Then ; While $avArray[$L][$iSubItem] < $vPivot While ($iStep * ($avArray[$L][$iSubItem] - $vPivot) < 0 And IsNumber($avArray[$L][$iSubItem])) Or (Not IsNumber($avArray[$L][$iSubItem]) And $iStep * StringCompare($avArray[$L][$iSubItem], $vPivot) < 0) $L += 1 WEnd ; While $avArray[$R][$iSubItem] > $vPivot While ($iStep * ($avArray[$R][$iSubItem] - $vPivot) > 0 And IsNumber($avArray[$R][$iSubItem])) Or (Not IsNumber($avArray[$R][$iSubItem]) And $iStep * StringCompare($avArray[$R][$iSubItem], $vPivot) > 0) $R -= 1 WEnd Else While ($iStep * StringCompare($avArray[$L][$iSubItem], $vPivot) < 0) $L += 1 WEnd While ($iStep * StringCompare($avArray[$R][$iSubItem], $vPivot) > 0) $R -= 1 WEnd EndIf ; Swap If $L <= $R Then For $i = 0 To $iSubMax $vTmp = $avArray[$L][$i] $avArray[$L][$i] = $avArray[$R][$i] $avArray[$R][$i] = $vTmp Next $L += 1 $R -= 1 EndIf Until $L > $R __ArrayQuickSort2D($avArray, $iStep, $iStart, $R, $iSubItem, $iSubMax) __ArrayQuickSort2D($avArray, $iStep, $L, $iEnd, $iSubItem, $iSubMax) EndFunc ;==>__ArrayQuickSort2D ; #FUNCTION# ==================================================================================================================== ; Name...........: _ArrayReverse ; Description ...: Takes the given array and reverses the order in which the elements appear in the array. ; Syntax.........: _ArrayReverse(ByRef $avArray[, $iStart = 0[, $iEnd = 0]]) ; Parameters ....: $avArray - Array to modify ; $iStart - [optional] Index of array to start modifying at ; $iEnd - [optional] Index of array to stop modifying at ; Return values .: Success - 1 ; Failure - 0, sets @error: ; |1 - $avArray is not an array ; |2 - $iStart is greater than $iEnd ; |3 - $avArray is not a 1 dimensional array ; Author ........: Brian Keene ; Modified.......: Jos van der Zande <jdeb at autoitscript dot com> - added $iStart parameter and logic, Tylo - added $iEnd parameter and rewrote it for speed, Ultima - code cleanup, minor optimization ; Remarks .......: ; Related .......: _ArraySwap ; Link ..........: ; Example .......: Yes ; =============================================================================================================================== Func _ArrayReverse(ByRef $avArray, $iStart = 0, $iEnd = 0) If Not IsArray($avArray) Then Return SetError(1, 0, 0) If UBound($avArray, 0) <> 1 Then Return SetError(3, 0, 0) Local $vTmp, $iUBound = UBound($avArray) - 1 ; Bounds checking If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound If $iStart < 0 Then $iStart = 0 If $iStart > $iEnd Then Return SetError(2, 0, 0) ; Reverse For $i = $iStart To Int(($iStart + $iEnd - 1) / 2) $vTmp = $avArray[$i] $avArray[$i] = $avArray[$iEnd] $avArray[$iEnd] = $vTmp $iEnd -= 1 Next Return 1 EndFunc ;==>_ArrayReverse ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now