blindwig Posted June 23, 2005 Share Posted June 23, 2005 (edited) I wrote a function that takes 2 arrays and returns an array containing all the elements common to both source arrays. It also strips these common elements out of the source arrays. Sidenote: I'm calling my array UDFs _Array1*, because I deal mostly with 1-based arrays. Some of my functions accept 0-based array input, but always output 1-based arrays. Here comes the code: CODE ;=============================================================================== ; ; Function Name: _Array1PullCommon() ; Description: Pulls all the common elements out of 2 given arrays and returns an array of these common elements. ; Parameter(s): $A1 and $A2 are 1-dimensional arrays, and $ArrayBase specifys weather they are 0- or 1-based ; Requirement(s): ; Return Value(s): Success: A 1-based array containung the elements common between arrays $a1 and $a2 ; Failure: Empty String ; Note: Upon return, $a1 and $a2 will be 1-based, regardless of their base before the function call ; Note: Upon return, $a1 and $a2 will not longer contain the common elements ; Note: Upon return, $a1, $a2, and the returned array will all be sorted ; Author(s): Mike Ratzlaff <mike@ratzlaff.org> ; Revision: 20050622A ; ;=============================================================================== ; ;Pulls the common elements out of $a1 and $a2, returns them in an array ;note: on return, all 3 arrays ($a1, $a2, and the returned array) are 1-based arrays Func _Array1PullCommon(ByRef $a1, ByRef $a2, $ArrayBase = 1, $ProgressTitle = @ScriptName) Dim $a1ndx, $a2ndx, $a1top, $a2top ;input check If Not (IsArray($a1) And IsArray($a2)) Then SetError(1) Return '' EndIf ;Setup If $ArrayBase Then $ArrayBase = 1 $a1Top = $a1[0] $a2Top = $a2[0] Else $ArrayBase = 0 $a1Top = UBound($a1) - 1 $a2Top = UBound($a2) - 1 EndIf If $a1top >= UBound($a1) or $a2top >= UBound($a2) Then SetError(1) Return '' EndIf $a1ndx = $ArrayBase $a2ndx = $ArrayBase Dim $a1new[$a1top + 1], $a2new[$a2top + 1] If $a1top > $a2top Then Dim $a3new[$a1top] Else Dim $a3new[$a2top] EndIf If $ProgressTitle <> '' Then ProgressOn($ProgressTitle, 'Comparing Lists...','',-1,-1,16) If $ProgressTitle <> '' Then ProgressSet(16) _ArraySort($a1, 0, $ArrayBase, $a1top) If $ProgressTitle <> '' Then ProgressSet(33) _ArraySort($a2, 0, $ArrayBase, $a2top) If $ProgressTitle <> '' Then ProgressSet(50) ;compare arrays side-by-side While $a1ndx <= $a1Top and $a2ndx <= $a2top While $a1ndx <= $a1top And $a2ndx <= $a2top And $a1[$a1ndx] < $a2[$a2ndx] $a1new[0] = $a1new[0] + 1 $a1new[$a1new[0]] = $a1[$a1ndx] $a1ndx = $a1ndx + 1 WEnd While $a1ndx <= $a1top And $a2ndx <= $a2top And $a1[$a1ndx] > $a2[$a2ndx] $a2new[0] = $a2new[0] + 1 $a2new[$a2new[0]] = $a2[$a2ndx] $a2ndx = $a2ndx + 1 WEnd If $a1ndx <= $a1top And $a2ndx <= $a2top And $a1[$a1ndx] = $a2[$a2ndx] Then $a3new[0] = $a3new[0] + 1 $a3new[$a3new[0]] = $a1[$a1ndx] $a1ndx = $a1ndx + 1 $a2ndx = $a2ndx + 1 EndIf If $ProgressTitle <> '' Then ProgressSet(50 + (($a1ndx + $a2ndx) * 50) / ($a1Top + $a2Top) ) WEnd ;finish out the arrays While $a1ndx <= $a1Top $a1new[0] = $a1new[0] + 1 $a1new[$a1new[0]] = $a1[$a1ndx] $a1ndx = $a1ndx + 1 If $ProgressTitle <> '' Then ProgressSet(50 + (($a1ndx + $a2ndx) * 50) / ($a1Top + $a2Top) ) WEnd While $a2ndx <= $a2Top $a2new[0] = $a2new[0] + 1 $a2new[$a2new[0]] = $a2[$a2ndx] $a2ndx = $a2ndx + 1 If $ProgressTitle <> '' Then ProgressSet(50 + (($a1ndx + $a2ndx) * 50) / ($a1Top + $a2Top) ) WEnd ;trim the new arrays ReDim $a1new[$a1new[0] + 1] ReDim $a2new[$a2new[0] + 1] ReDim $a3new[$a3new[0] + 1] If $ProgressTitle <> '' Then ProgressOff() ;return the new arrays $a1 = $a1new $a2 = $a2new Return $a3new EndFunc Edited June 24, 2005 by blindwig My UDF Threads:Pseudo-Hash: Binary Trees, Flat TablesFiles: Filter by Attribute, Tree List, Recursive Find, Recursive Folders Size, exported to XMLArrays: Nested, Pull Common Elements, Display 2dSystem: Expand Environment Strings, List Drives, List USB DrivesMisc: Multi-Layer Progress Bars, Binary FlagsStrings: Find Char(s) in String, Find String in SetOther UDF Threads I Participated:Base64 Conversions Link to comment Share on other sites More sharing options...
blindwig Posted June 24, 2005 Author Share Posted June 24, 2005 Found sound bugs in my logic, fixed the code. Also added an optional progress meter. Edited the above post. My UDF Threads:Pseudo-Hash: Binary Trees, Flat TablesFiles: Filter by Attribute, Tree List, Recursive Find, Recursive Folders Size, exported to XMLArrays: Nested, Pull Common Elements, Display 2dSystem: Expand Environment Strings, List Drives, List USB DrivesMisc: Multi-Layer Progress Bars, Binary FlagsStrings: Find Char(s) in String, Find String in SetOther UDF Threads I Participated:Base64 Conversions Link to comment Share on other sites More sharing options...
jftuga Posted October 19, 2005 Share Posted October 19, 2005 How would you change this code so that it returned elements not contained in both? For example: $array1 contains 3456, 4567, 5678 $array2 contains 9999, 3456, 4567, 5678, 1111 I would want returned an array with just 9999 and 1111 in it. Thanks, -John Admin_Popup, show computer info or launch shellRemote Manager, facilitates connecting to RDP / VNCProc_Watch, reprioritize cpu intensive processesUDF: _ini_to_dict, transforms ini file entries into variablesUDF: monitor_resolutions, returns resolutions of multiple monitorsReport Computer Problem, for your IT help deskProfile Fixer, fixes a 'missing' AD user profile Link to comment Share on other sites More sharing options...
blindwig Posted November 17, 2005 Author Share Posted November 17, 2005 How would you change this code so that it returned elements not contained in both?For example:$array1 contains 3456, 4567, 5678 $array2 contains 9999, 3456, 4567, 5678, 1111I would want returned an array with just 9999 and 1111 in it.Thanks,-JohnSorry this reply is pretty late, but if you still need an answer:Using code:$a3=_Array1PullCommon($a1, $a2)Now $a3 contains a list of common elements, and $a1 and $a2 contain the unique elements. So if you want a list of unique elements, just join or merge the two arrays:$a4=_ArrayMerge($a1, $a2)and now $a4 will contain the complete list of unique elements.Do a search for an array merging routine, I'm sure that there are a few here somewhere... My UDF Threads:Pseudo-Hash: Binary Trees, Flat TablesFiles: Filter by Attribute, Tree List, Recursive Find, Recursive Folders Size, exported to XMLArrays: Nested, Pull Common Elements, Display 2dSystem: Expand Environment Strings, List Drives, List USB DrivesMisc: Multi-Layer Progress Bars, Binary FlagsStrings: Find Char(s) in String, Find String in SetOther UDF Threads I Participated:Base64 Conversions Link to comment Share on other sites More sharing options...
J_Y_C Posted November 10, 2006 Share Posted November 10, 2006 I am getting an error when using this function: ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.: $a1new[$a1new[0]] = $a1[$a1ndx] ^ ERROR before I spend too much time trying to wrap my head around why this is happening, do you know off the top of your head what it may be? 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