Trong Posted September 27, 2015 Share Posted September 27, 2015 How to Sort a array by string length ?String: B|A|A|C|C|AB|DDD|BAAS|003|100|02 ----TO-> A|B|C|02|AB|003|100|DDD|BAAS#include <Array.au3> Local $sWord, $sWordList = ("B|A|A|C|C|AB|DDD|BAAS|003|100|02") Local $sListWord = StringSplit($sWordList, "|") $sListWord=__ArrayUnique($sListWord) _ArraySort($sListWord,0,1) For $i = 1 To UBound($sListWord) - 1 $sWord = $sListWord[$i] ConsoleWrite($sWord &"|") Next ConsoleWrite(@CRLF) Func __ArrayUnique($sArray) If Not IsArray($sArray) Then Return SetError(1) If UBound($sArray, 0) > 1 Then Return SetError(2) Local $NewArr[1], $IsFound=0, $NewArrCnt=0, $Extended=0 For $i = 1 To UBound($sArray) - 1 $IsFound = 0 For $j = 1 To UBound($NewArr)-1 If $sArray[$i] = $NewArr[$j] Then $IsFound = 1 $Extended += 1 ExitLoop EndIf Next If Not $IsFound Then $NewArrCnt += 1 ReDim $NewArr[$NewArrCnt+1] $NewArr[$NewArrCnt] = $sArray[$i] EndIf Next $NewArr[0] = UBound($NewArr) - 1 Return SetError(0, $Extended, $NewArr) EndFunc Regards, Link to comment Share on other sites More sharing options...
jguinch Posted September 27, 2015 Share Posted September 27, 2015 Maybe this could help you : https://www.autoitscript.com/forum/topic/124437-sort-multiple-or-multi-dimensional-arrays-with-multiple-sort-columns/ Trong 1 Spoiler Network configuration UDF, _DirGetSizeByExtension, _UninstallList Firefox ConfigurationArray multi-dimensions, Printer Management UDF Link to comment Share on other sites More sharing options...
iamtheky Posted September 27, 2015 Share Posted September 27, 2015 (edited) nm, misunderstood...too early fts. Edited September 27, 2015 by boththose Trong 1 ,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-. |(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/ (_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_) | | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) ( | | | | |)| | \ / | | | | | |)| | `--. | |) \ | | `-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_| '-' '-' (__) (__) (_) (__) Link to comment Share on other sites More sharing options...
Trong Posted September 27, 2015 Author Share Posted September 27, 2015 @jguinch I do not make it work with your suggestion.@boththose I do not understand what are you saying. Regards, Link to comment Share on other sites More sharing options...
czardas Posted September 27, 2015 Share Posted September 27, 2015 #include <Array.au3> Local $aTest = ["Yo","Hi","1","very long","longer","long"] _ArraySortByLen($aTest) _ArrayDisplay($aTest) Func _ArraySortByLen(ByRef $aArray, $iDescending =0, $iStart =0, $iEnd =0) If Not IsArray($aArray) Or UBound($aArray, 0) > 1 Then Return SetError(1, 0, 0) ; Not a 1D array If Not IsInt($iStart) Or Not IsInt($iEnd) Then Return SetError(5, 0, 0) ; Parameters need to be integers. Local $iBound = UBound($aArray) Local $aElementLen[$iBound][2] $iBound -=1 For $i = 0 To $iBound $aElementLen[$i][0] = StringLen($aArray[$i]) ; Get the length of the element $aElementLen[$i][1] = $aArray[$i] ; The element to sort Next _ArraySort($aElementLen, $iDescending, $iStart, $iEnd) If @error Then Return SetError(@error, 0, 0) ; See _ArraySort() for error codes 2 to 4. For $i = 0 To $iBound $aArray[$i] = $aElementLen[$i][1] Next Return 1 EndFunc ;==> _ArraySortByLen() Trong 1 operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
czardas Posted September 27, 2015 Share Posted September 27, 2015 (edited) That's old code. Try this modified version.#include <Array.au3> Local $sWordList = ["B","A","A","C","C","AB","DDD","BAAS","003","100","02"] _ArraySortByLen($sWordList) _ArrayDisplay($sWordList) Func _ArraySortByLen(ByRef $aArray, $iDescending =0, $iStart =0, $iEnd =0) If Not IsArray($aArray) Or UBound($aArray, 0) > 1 Then Return SetError(1, 0, 0) ; Not a 1D array If Not IsInt($iStart) Or Not IsInt($iEnd) Then Return SetError(5, 0, 0) ; Parameters need to be integers. Local $iBound = UBound($aArray) Local $aElementLen[$iBound][2] $iBound -=1 For $i = 0 To $iBound $aElementLen[$i][0] = StringFormat("%08i", StringLen($aArray[$i])) & $aArray[$i] ; Get the length of the element $aElementLen[$i][1] = $aArray[$i] ; The element to sort Next _ArraySort($aElementLen, $iDescending, $iStart, $iEnd) If @error Then Return SetError(@error, 0, 0) ; See _ArraySort() for error codes 2 to 4. For $i = 0 To $iBound $aArray[$i] = $aElementLen[$i][1] Next Return 1 EndFunc ;==> _ArraySortByLen() Edited September 27, 2015 by czardas Trong 1 operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
Trong Posted September 27, 2015 Author Share Posted September 27, 2015 Thanks @czardas Regards, Link to comment Share on other sites More sharing options...
iamtheky Posted September 27, 2015 Share Posted September 27, 2015 #include<array.au3> $sString = "B|A|A|C|C|AB|DDD|BAAS|003|100|02" $aSplit = stringsplit($sString , "|" , 2) _arraySort($aSplit) local $aNew[0] local $maxlen = 0 For $m = 0 to ubound($aSplit) - 1 $curlen = stringlen($aSplit[$m]) If $curlen > $maxlen Then $maxlen = $curlen Next For $k = 0 to $maxlen For $i = 0 to ubound($aSplit) - 1 If stringlen($aSplit[$i]) = $k Then _arrayadd($aNew , $aSplit[$i]) EndIf Next Next _ArrayDisplay($aNew) Trong 1 ,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-. |(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/ (_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_) | | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) ( | | | | |)| | \ / | | | | | |)| | `--. | |) \ | | `-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_| '-' '-' (__) (__) (_) (__) Link to comment Share on other sites More sharing options...
czardas Posted September 27, 2015 Share Posted September 27, 2015 (edited) Yeah that's a possible method. You could make it go faster by replacing _ArrayAdd() to avoid ReDims. First create an empty array with all the elements needed, and then fill it using your method. Edited September 27, 2015 by czardas Trong 1 operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
iamtheky Posted September 27, 2015 Share Posted September 27, 2015 (edited) i was going for line count. efficiency would be your method. I have to think you can get rid of the stringlength loop in a smart way as well.this maybe? Edit: *No this is definitely doing something wrong, changing the array slightly messes it up#include<array.au3> $sString = "B|A|A|C|C|AB|DDD|BAAS|003|100|02" $aSplit = stringsplit($sString , "|" , 2) _arraySort($aSplit) local $aNew[0] local $maxlen = 0 local $i = 0 For $k = 0 to stringlen($aSplit[$i]) + 1 For $i = 0 to ubound($aSplit) - 1 If stringlen($aSplit[$i]) = $k Then _arrayadd($aNew , $aSplit[$i]) EndIf Next Next _ArrayDisplay($aNew) Edited September 27, 2015 by boththose Trong 1 ,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-. |(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/ (_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_) | | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) ( | | | | |)| | \ / | | | | | |)| | `--. | |) \ | | `-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_| '-' '-' (__) (__) (_) (__) Link to comment Share on other sites More sharing options...
Trong Posted September 27, 2015 Author Share Posted September 27, 2015 Smart brains @czardas & @boththose Regards, Link to comment Share on other sites More sharing options...
UEZ Posted September 27, 2015 Share Posted September 27, 2015 Here another versionexpandcollapse popup#include <Array.au3> Local $sWord, $sWordList = ("B|A|A|C|C|AB|DDD|BAAS|003|100|02") $aResult = Sort($sWordList) _ArrayDisplay($aResult) Func Sort($sData, $sDelimiter = "|") Local $a = _ArrayUnique(StringSplit($sData, $sDelimiter, 2), 0, 0, 0, 0), $i Local $aResult[UBound($a)][2] For $i = 0 To UBound($a) - 1 $aResult[$i][0] = $a[$i] $aResult[$i][1] = StringLen($a[$i]) Next Local $aI[2] = [1, 0] _ArraySort_MultiColumn($aResult, $aI, 0) ReDim $aResult[UBound($aResult)][1] Return $aResult EndFunc ; #FUNCTION# ============================================================================= ; Name.............: _ArraySort_MultiColumn ; Description ...: sorts an array at given colums (multi colum sort) ; Syntax...........: _ArraySort_MultiColumn(ByRef $aSort, ByRef $aIndices) ; Parameters ...: $aSort - array to sort ; $aIndices - array with colum indices which should be sorted in specified order - zero based ; $oDir/$iDir - sort direction - if set to 1, sort descendingly else ascendingly ; Author .........: UEZ ; Version ........: v0.70 build 2013-11-20 Beta ; ========================================================================================= Func _ArraySort_MultiColumn(ByRef $aSort, ByRef $aIndices, $oDir = 0, $iDir = 0) If Not IsArray($aIndices) Or Not IsArray($aSort) Then Return SetError(1, 0, 0) ;checks if $aIndices is an array If UBound($aIndices) > UBound($aSort, 2) Then Return SetError(2, 0, 0) ;check if $aIndices array is greater the $aSort array Local $1st, $2nd, $x, $j, $k, $l = 0 For $x = 0 To UBound($aIndices) - 1 ;check if array content makes sense If Not IsInt($aIndices[$x]) Then Return SetError(3, 0, 0) ;array content is not numeric Next If UBound($aIndices) = 1 Then Return _ArraySort($aSort, $oDir, 0, 0, $aIndices[0]) ;check if only one index is given _ArraySort($aSort, $oDir, 0, 0, $aIndices[0]) Do $1st = $aIndices[$l] $2nd = $aIndices[$l + 1] $j = 0 $k = 1 While $k < UBound($aSort) If $aSort[$j][$1st] <> $aSort[$k][$1st] Then If $k - $j > 1 Then _ArraySort($aSort, $iDir , $j, $k - 1, $2nd) $j = $k Else $j = $k EndIf EndIf $k += 1 WEnd If $k - $j > 1 Then _ArraySort($aSort, $iDir, $j, $k, $2nd) $l += 1 Until $l = UBound($aIndices) - 1 Return 1 EndFunc Trong 1 Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
czardas Posted September 27, 2015 Share Posted September 27, 2015 I have to think you can get rid of the stringlength loop in a smart way as well.Probably RegExp can do this with the string syntax provided. I'm not sure how, but I think so. Trong 1 operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
iamtheky Posted September 27, 2015 Share Posted September 27, 2015 (edited) down to two loops#include<array.au3> $sString = "B|A|A|C|C|AB|DDDDDDDdD|BAAS|003|100|02" $aSplit = stringsplit($sString , "|" , 2) _arraySort($aSplit) local $aNew[0] $i = 0 For $k = 0 to stringlen($aSplit[ubound($aSplit) - 1]) + 1 For $i = 0 to ubound($aSplit) - 1 If stringlen($aSplit[$i]) = $k Then _arrayadd($aNew , $aSplit[$i]) EndIf Next Next _ArrayDisplay($aNew) Edited September 27, 2015 by boththose Trong 1 ,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-. |(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/ (_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_) | | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) ( | | | | |)| | \ / | | | | | |)| | `--. | |) \ | | `-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_| '-' '-' (__) (__) (_) (__) Link to comment Share on other sites More sharing options...
czardas Posted September 27, 2015 Share Posted September 27, 2015 (edited) Broke it with: "B|A|A|C|C|AB|0DDDDDdD|BAAS|003|100|02". Your method also loops through the array multiple times. Edited September 27, 2015 by czardas Trong 1 operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
jguinch Posted September 27, 2015 Share Posted September 27, 2015 With #2, I had the same idea than UEZ, but I did not take the time to explain it, sorry.BTW, something else maybe interesting with one single loop :#include<array.au3> $sString = "B|A|A|C|C|AB|DDD|BAAS|003|100|02" $iMaxLen = 0*StringReplace($sString, "|", "") + @extended $s = Execute("'" & StringRegExpReplace($sString, "([^|]+)", "' & StringFormat('%0' & " & $iMaxLen & " & 'i', StringLen('$1')) & ';$1' & '") & "'") $res = StringRegExp($s, "[^|]+", 3) _ArraySort($res) For $i = 0 To UBound($res) - 1 $res[$i] = StringTrimLeft($res[$i], $iMaxLen + 1) Next _ArrayDisplay($res) czardas and Trong 2 Spoiler Network configuration UDF, _DirGetSizeByExtension, _UninstallList Firefox ConfigurationArray multi-dimensions, Printer Management UDF Link to comment Share on other sites More sharing options...
iamtheky Posted September 27, 2015 Share Posted September 27, 2015 (edited) arraysort is a fickle whore.And I was not saying I only loop twice... I was just saying my effort is down from 3 For loops to 2, keyboard strokes. @jguinchnot that its feasible, but why does yours break with a single quote, but every other character seems fine? * (looks like it terminates the execute string, but i will wait for the expert diagnosis.)$sString = "B|A|A|C'|C|AB|DDD|BAAS|003|100|02" Edited September 27, 2015 by boththose Trong 1 ,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-. |(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/ (_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_) | | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) ( | | | | |)| | \ / | | | | | |)| | `--. | |) \ | | `-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_| '-' '-' (__) (__) (_) (__) Link to comment Share on other sites More sharing options...
czardas Posted September 27, 2015 Share Posted September 27, 2015 (edited) @jguinch Very nice. Thinking about it, $iMaxlen could generate some rather long strings. Maybe you could use StringLen($iMaxlen) instead. Or use 8: because arrays can't grow beyond appox 16,000,000 elements (8 digits).Hmm that's faulty thinking. The longest string may be longer than 16,000,000 99,999,999 characters. Edited September 27, 2015 by czardas Trong 1 operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
jguinch Posted September 27, 2015 Share Posted September 27, 2015 Thanks@boththose : you just have to double the single quotes before the execute call$s = Execute("'" & StringRegExpReplace(StringReplace($sString, "'", "''"), "([^|]+)", "' & StringFormat('%0' & " & $iMaxLen & " & 'i', StringLen('$1')) & ';$1' & '") & "'") Trong 1 Spoiler Network configuration UDF, _DirGetSizeByExtension, _UninstallList Firefox ConfigurationArray multi-dimensions, Printer Management UDF Link to comment Share on other sites More sharing options...
czardas Posted September 27, 2015 Share Posted September 27, 2015 (edited) Maybe prefix the maximum zero digits you want to allow - probably not more than 10. A 10 digit number would be a huge string length. Edited September 27, 2015 by czardas Trong 1 operator64 ArrayWorkshop 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