Jump to content



Photo

UDF: _Array1PullCommon


  • Please log in to reply
4 replies to this topic

#1 blindwig

blindwig

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 772 posts

Posted 23 June 2005 - 07:14 PM

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 by blindwig, 24 June 2005 - 01:49 AM.






#2 blindwig

blindwig

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 772 posts

Posted 24 June 2005 - 01:50 AM

Found sound bugs in my logic, fixed the code. Also added an optional progress meter. Edited the above post.

#3 jftuga

jftuga

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 315 posts

Posted 19 October 2005 - 07:52 PM

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

#4 blindwig

blindwig

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 772 posts

Posted 17 November 2005 - 12:31 AM

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

Sorry 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...

#5 J_Y_C

J_Y_C

    Wayfarer

  • Active Members
  • Pip
  • 80 posts

Posted 10 November 2006 - 07:22 PM

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?




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users