Pilot123 Posted July 4, 2015 Share Posted July 4, 2015 (edited) Hi, In this 1-dimensional array, I have two 'groups' of array indexes, with the value "red" in it.#include <Array.au3> Local $aArray[10] = [1, 2, "red", "red", "red", 6, 7, "red", "red", 10] ; Create a 1-dimensional array that contains duplicate values. _ArrayDisplay($aArray, "$aArray Initial") ; Display the current array.Group 1Index2= redIndex3= redIndex4= red Group 2Index7= redIndex8= red Could someone please help me with a script that will test the array for a group/groups with the specific value "red", and then display a message box for example:Group 1 starts with index2, and ends with index4 Group 2 starts with index7, and ends with index8Thanks, Edited July 4, 2015 by Pilot123 Link to comment Share on other sites More sharing options...
Luigi Posted July 4, 2015 Share Posted July 4, 2015 Maybe this?expandcollapse popup#include <Array.au3> Local $aArray[10] = [1, 2, "red", "red", "red", 6, 7, "red", "red", 10] ;~ [0, 1, 2 3, 4, 5, 6, 7, 8, 9 ] ;~ Local $aArray[1] = [1] Local $oGroup = group($aArray) ConsoleWrite("number of groups[ " & $oGroup.Count & " ]" & @LF) For $each In $oGroup ConsoleWrite("$each[ " & $each & " ] ids[ " & $oGroup.Item($each) & " ]" & @LF) Next Func group($aInput) Local $oRet = ObjCreate("Scripting.Dictionary") Local $iStart Local $aRet[1] If Not IsArray($aInput) Or UBound($aInput, 1) <= 1 Then Return $oRet For $ii = 1 To UBound($aInput, 1) - 1 If $aInput[$ii] = $aInput[$ii - 1] Then If $iStart Then _ArrayAdd($aRet, $ii) Else $iStart = $ii - 1 _ArrayAdd($aRet, $ii - 1) _ArrayAdd($aRet, $ii) EndIf Else If $iStart Then $oRet.Add($oRet.Count + 1, _ArrayToString($aRet, "|", 1)) Local $aRet[1] $iStart = 0 EndIf EndIf Next Return $oRet EndFunc ;==>group Visit my repository Link to comment Share on other sites More sharing options...
mikell Posted July 4, 2015 Share Posted July 4, 2015 (edited) Without using cpu consuming _Array* funcs #include <Array.au3> ; for display only Local $aArray[14] = ["red", "red", 1, 2, "red", "red", "red", 6, 7, "red", "red", 10, "red", "red"] _ArrayDisplay($aArray, "$aArray Initial") ; Display the current array. $announce = _group($aArray, "red") $nb = StringReplace($announce, @crlf, @crlf) Msgbox(0, @extended & " groups", $announce) Func _group($array, $txt) Local $a, $u = UBound($array), $res[$u][2], $n, $k = 0, $announce = "" For $i = 0 to $u-1 If $array[$i] = $txt and $n = 0 Then $n = 1 $res[$k][0] = $i EndIf If ($array[$i] <> $txt or $i = $u-1) and $n = 1 Then $res[$k][1] = ($array[$i] = $txt and $i = $u-1) ? $i : $i-1 $n = 0 $k += 1 EndIf Next ; Redim $res[$k][2] ; can be useful if you plan to return the array ; _ArrayDisplay($res) For $i = 0 to $k-1 $announce &= "Group" & $i+1 & " starts with " & $res[$i][0] & ", and ends with " & $res[$i][1] & @crlf Next Return $announce EndFunc Edited July 4, 2015 by mikell Link to comment Share on other sites More sharing options...
Pilot123 Posted July 4, 2015 Author Share Posted July 4, 2015 Thank you very much mikell, this is exactly what I am looking for. I will study your code and implement it in my project code. Link to comment Share on other sites More sharing options...
Gianni Posted July 4, 2015 Share Posted July 4, 2015 Without using cpu consuming _Array* funcs try with this arrayLocal $aArray[14] = [0, 0, 1, 2, 0, 0, 0, 6, 7, 0, 0, 10, 0, 0] p.s.it fails also with @Luigi function Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
Luigi Posted July 4, 2015 Share Posted July 4, 2015 (edited) Hum... @Chimp is a bugfinder! Greate! ^^Try this:expandcollapse popup#include <Array.au3> ;~ Local $aArray[10] = [1, 2, "red", "red", "red", 6, 7, "red", "red", 10] Local $aArray[14] = [0, 0, 1, 2, 0, 0, 0, 6, 7, 0, 0, 9, 0, 0] ;~ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13] ;~ [0, 1, 2 3, 4, 5, 6, 7, 8, 9 ] ;~ Local $aArray[1] = [1] Local $oGroup = group($aArray) ConsoleWrite("number of groups[ " & $oGroup.Count & " ]" & @LF) For $each In $oGroup ConsoleWrite("$each[ " & $each & " ] ids[ " & $oGroup.Item($each) & " ]" & @LF) Next Func group($aInput) Local $oRet = ObjCreate("Scripting.Dictionary") Local $iStart Local $aRet[1] If Not IsArray($aInput) Or UBound($aInput, 1) <= 1 Then Return $oRet For $ii = 1 To UBound($aInput, 1) - 1 If ($aInput[$ii]) = ($aInput[$ii - 1]) Then If $iStart Then _ArrayAdd($aRet, $ii) Else $iStart = $ii - 1 _ArrayAdd($aRet, $ii - 1) _ArrayAdd($aRet, $ii) EndIf ElseIf UBound($aRet, 1) > 1 Then $oRet.Add($oRet.Count + 1, _ArrayToString($aRet, "|", 1)) Local $aRet[1] $iStart = 0 EndIf Next If $aInput[UBound($aInput, 1) - 1] = $aInput[UBound($aInput, 1) - 2] Then $oRet.Add($oRet.Count + 1, _ArrayToString($aRet, "|", 1)) Return $oRet EndFunc ;==>group Edited July 4, 2015 by Luigi Visit my repository Link to comment Share on other sites More sharing options...
mikell Posted July 4, 2015 Share Posted July 4, 2015 Chimp, what doesn't work for you ?I tried with your array and got no error and correct resultsThe only thing I just see now is that a confusion may occur between a string and the number 0 Link to comment Share on other sites More sharing options...
Pilot123 Posted July 5, 2015 Author Share Posted July 5, 2015 Hi again,One last question. How can I adapt @mikell example code so that each index number of the $aArray that is written to the message box , is also matched with a second $bArray index,and those values passed to variables, so that I can use them in my other code. Let's say the possible groups in my $aArray will not exceed 4.My second additional array I want to add:Local $bArray[14] = ["Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf", "Hotel", "India", "Juliet", "Kilo", "Lima", "Mike", "November"]This is the output of the message box from @mikell's code:Group1 starts with 0, and ends with 1 Group2 starts with 4, and ends with 6 Group3 starts with 9, and ends with 10 Group4 starts with 12, and ends with 13So, the value 0 in the message box above , equals the stored location with the index0, of $aArrayand, the value 1 equals the stored location with the index1, of $aArrayand, the value 4 equals the stored location with the index4, of $aArray, etc.. What I need is that when, the value 0 (representing index0) is written to the message box, it also goes to the second array $bArray and goes to its index0, and reads the element stored in that location and writes it to the variable $a = "Alpha", for example.The variables will then look like this:$a = "Alpha" $b = "Bravo" $c = "Echo" $d = "Golf" $e = "Juliet" $f = "Kilo" $g = "Mike" $h = "November If a group only consists of one element, for example; Group3 starts with 9, and ends with 9Then the variables for group 3 will be:$e = "Juliet" $f = "Juliet"If would appreciate if someone can help me with this please Link to comment Share on other sites More sharing options...
mikell Posted July 5, 2015 Share Posted July 5, 2015 (edited) For this you have to return the array from the func and then apply the result to $bArray (which is not a nice name in terms of hungarian notation, should be i.e. $aArray1 and $aArray2)#include <Array.au3> Local $aArray1[14] = ["red", "red", 1, 2, "red", "red", "red", 6, 7, "red", 9, 10, "red", "red"] Local $aArray2[14] = ["Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf", "Hotel", "India", "Juliet", "Kilo", "Lima", "Mike", "November"] ;_ArrayDisplay($aArray, "$aArray Initial") $aGr = _group($aArray1, "red") _ArrayDisplay($aGr) Local $aNew[UBound($aGr)*2] For $i = 0 to UBound($aGr)*2-2 step 2 $aNew[$i] = $aArray2[$aGr[$i/2][0] ] $aNew[$i+1] = $aArray2[$aGr[$i/2][1] ] Next _ArrayDisplay($aNew) Func _group($array, $txt) Local $u = UBound($array), $aRes[$u][2], $n, $k For $i = 0 to $u-1 If $array[$i] = $txt and $n = 0 Then $n = 1 $aRes[$k][0] = $i EndIf If ($array[$i] <> $txt or $i = $u-1) and $n = 1 Then $aRes[$k][1] = ($array[$i] = $txt and $i = $u-1) ? $i : $i-1 $n = 0 $k += 1 EndIf Next Redim $aRes[$k][2] Return $aRes EndFuncThen you can use the elements of the new array as variables (or assign them to variables)EditThe added code part could easily be included in the func using the 2nd array as a parameter Edited July 5, 2015 by mikell Link to comment Share on other sites More sharing options...
Pilot123 Posted July 5, 2015 Author Share Posted July 5, 2015 Thanks you very much Mikell, again looks like exactly what I need.As a newbie, I still need a lot of practice!!I'll study your example code again.Thanks, Link to comment Share on other sites More sharing options...
Gianni Posted July 5, 2015 Share Posted July 5, 2015 (edited) @mikellyour function is nearly ok, but if you have an input array like that one I've posted above, your function will consider any presence of the number 0 like if it is the searched word, even if it's not. maybe if you change the comparison statementIf $array[$i] = $txt and $n = 0 Thenby using a double == instead of just one =, then the problem do not arise.If $array[$i] == $txt and $n = 0 Then@Luigi, Your function finds if there are 2 or more consecutive elements with the same value in the array. Any word is ok, not just the wanted word ("red" in this case).One more bug is that if the wanted word appears one or more times in the array but none of them is alongside another, the function simply do not consider that word even if should be considered instead. Edited July 5, 2015 by Chimp Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
mikell Posted July 5, 2015 Share Posted July 5, 2015 Chimp,You're right, forcing string comparison is the solution but I'll use String() rather than == (because == forces case sensitivity) Link to comment Share on other sites More sharing options...
Gianni Posted July 5, 2015 Share Posted July 5, 2015 (edited) Hi again,One last question. How can I adapt @mikell example code so that each index number of the $aArray that is written to the message box , is also matched with a second $bArray index,and those values passed to variables, so that I can use them in my other code. Let's say the possible groups in my $aArray will not exceed 4.My second additional array I want to add:Local $bArray[14] = ["Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf", "Hotel", "India", "Juliet", "Kilo", "Lima", "Mike", "November"]This is the output of the message box from @mikell's code:Group1 starts with 0, and ends with 1 Group2 starts with 4, and ends with 6 Group3 starts with 9, and ends with 10 Group4 starts with 12, and ends with 13So, the value 0 in the message box above , equals the stored location with the index0, of $aArrayand, the value 1 equals the stored location with the index1, of $aArrayand, the value 4 equals the stored location with the index4, of $aArray, etc.. What I need is that when, the value 0 (representing index0) is written to the message box, it also goes to the second array $bArray and goes to its index0, and reads the element stored in that location and writes it to the variable $a = "Alpha", for example.The variables will then look like this:$a = "Alpha" $b = "Bravo" $c = "Echo" $d = "Golf" $e = "Juliet" $f = "Kilo" $g = "Mike" $h = "November If a group only consists of one element, for example; Group3 starts with 9, and ends with 9Then the variables for group 3 will be:$e = "Juliet" $f = "Juliet"If would appreciate if someone can help me with this pleaseHi Pilot123Not sure what's your exact goal and if you already got your wanted answer, anyway I think that create a new variable for each value of starting and ending index of the found groups, is not the right way, and is not even a need.indeed, since you already have the $bArray with all needed values, you can simply read directly those values using the indexes from array of found groups.Of course the nr. of elements in the first array $aArray must be less or equal to the nr of elements of the second array $bArray otherwise you can get the "subscript dimension range exceeded" errormaybe an example is better than many words (expecially from a not native English speakers like me)hope it can help youhere one further way to go:expandcollapse popup#include <Array.au3> ; Input arrays Local $aArray[14] = ["red", "red", 1, 2, "red", "red", "red", 6, 7, "red", "red", 10, "red", "red"] ; Array with lookup values Local $bArray[14] = ["Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf", "Hotel", "India", "Juliet", "Kilo", "Lima", "Mike", "November"] Local $aResult = _FindGroups($aArray, "red", 0) If Not @error Then _ArrayDisplay($aResult, @extended & " groups found") Else MsgBox(0, "Error", "no groups found") EndIf ; now use indexes found in the $aResult array as indexes to point to values in your second array $bArray ; (we just use indexes from the first array to get the wanted data from the second array) Local $aMatches[UBound($aResult)][4] ; create another array with same number of rows as $aResult to hold first array and corresponding matches from the second array if IsArray($aResult) Then for $i = 0 to UBound($aResult) - 1 $aMatches[$i][0] = $aResult[$i][0] ; clone data from $aResult $aMatches[$i][1] = $aResult[$i][1] $aMatches[$i][2] = $bArray[$aResult[$i][0]] ; Get values from $bArray according to indexes from the $aResult array $aMatches[$i][3] = $bArray[$aResult[$i][1]] Next _ArrayDisplay($aMatches, "Correspondences with second array") EndIf ; -------------------------------------------------------------------------- ; General purpose function to find how a value is groupped within an 1D array ; $aArray : the input array ; $sTarget : the value to search string or value (i.e. 0 is <> from "0") ; $iCase : Case sensitive search 0=no 1=yes ; ; returns : on success: ; a 2D array with as many rows as many groups are found ; [n][0] and [n][1] index of first [0] and last [1] position of the n group ; @extended contains the number of rows (groups) found ; on error: ; returns -1 and set @error to 1 ; ------------------------------------------------------------------------- Func _FindGroups(ByRef $aArray, $sTarget, $iCase = 0, $iCompare = 2) Local $Targets = _ArrayFindAll($aArray, $sTarget, 0, 0, $iCase, $iCompare) If IsArray($Targets) Then _ArraySort($Targets, 1) Local $i = UBound($Targets) Local $aStack[$i + 1][2] ; make room for all possible indexes (only some of them will be usually used) $i -= 1 ; start parsing from last element back to first _Push($aStack, $Targets[$i]) While $i If $Targets[$i] = $Targets[$i - 1] - 1 Then ; do nothin and continue parsing Else _Push($aStack, $Targets[$i]) _Push($aStack, $Targets[$i - 1]) EndIf $i -= 1 WEnd _Push($aStack, $Targets[$i]) Return SetError(0, $aStack[0][0], _ArrayExtract($aStack, 1, $aStack[0][0])) EndIf Return SetError(1, 0, -1) EndFunc ;==>_FindGroups Func _Push(ByRef $aStack, $Value) ; 2D stack for internal use $aStack[0][1] = Not $aStack[0][1] $aStack[0][0] += $aStack[0][1] $aStack[$aStack[0][0]][Not $aStack[0][1]] = $Value EndFunc ;==>_Push Edited July 6, 2015 by Chimp Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
Pilot123 Posted July 6, 2015 Author Share Posted July 6, 2015 (edited) expandcollapse popup#include <Array.au3> ; Input arrays Local $aArray[14] = ["red", "red", 1, 2, "red", "red", "red", 6, 7, "red", "red", 10, "red", "red"] ; Array with lookup values Local $bArray[14] = ["Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf", "Hotel", "India", "Juliet", "Kilo", "Lima", "Mike", "November"] Local $aResult = _FindGroups($aArray, "red", 0) If Not @error Then _ArrayDisplay($aResult, @extended & " groups found") Else MsgBox(0, "Error", "no groups found") EndIf ; now use indexes found in the $aResult array as indexes to point to values in your second array $bArray ; (we just use indexes from the first array to get the wanted data from the second array) Local $aMatches[UBound($aResult)][4] ; create another array with same number of rows as $aResult to hold first array and corresponding matches from the second array if IsArray($aResult) Then for $i = 0 to UBound($aResult) - 1 $aMatches[$i][0] = $aResult[$i][0] ; clone data from $aResult $aMatches[$i][1] = $aResult[$i][1] $aMatches[$i][2] = $bArray[$aResult[$i][0]] ; Get values from $bArray according to indexes from the $aResult array $aMatches[$i][3] = $bArray[$aResult[$i][1]] Next _ArrayDisplay($aMatches, "Correspondences with second array") EndIf ; -------------------------------------------------------------------------- ; General purpose function to find how a value is groupped within an 1D array ; $aArray : the input array ; $sTarget : the value to search string or value (i.e. 0 is <> from "0") ; $iCase : Case sensitive search 0=no 1=yes ; ; returns : on success: ; a 2D array with as many rows as many groups are found ; [n][0] and [n][1] index of first [0] and last [1] position of the n group ; @extended contains the number of rows (groups) found ; on error: ; returns -1 and set @error to 1 ; ------------------------------------------------------------------------- Func _FindGroups(ByRef $aArray, $sTarget, $iCase = 0, $iCompare = 2) Local $Targets = _ArrayFindAll($aArray, $sTarget, 0, 0, $iCase, $iCompare) If IsArray($Targets) Then _ArraySort($Targets, 1) Local $i = UBound($Targets) Local $aStack[$i + 1][2] ; make room for all possible indexes (only some of them will be usually used) $i -= 1 ; start parsing from last element back to first _Push($aStack, $Targets[$i]) While $i If $Targets[$i] = $Targets[$i - 1] - 1 Then ; do nothin and continue parsing Else _Push($aStack, $Targets[$i]) _Push($aStack, $Targets[$i - 1]) EndIf $i -= 1 WEnd _Push($aStack, $Targets[$i]) Return SetError(0, $aStack[0][0], _ArrayExtract($aStack, 1, $aStack[0][0])) EndIf Return SetError(1, 0, -1) EndFunc ;==>_FindGroups Func _Push(ByRef $aStack, $Value) ; 2D stack for internal use $aStack[0][1] = Not $aStack[0][1] $aStack[0][0] += $aStack[0][1] $aStack[$aStack[0][0]][Not $aStack[0][1]] = $Value EndFunc ;==>_PushHi Chimp,Thanks.I included your code in my project. Working great so far. Edited July 9, 2015 by Pilot123 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