[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

matching lists




Hi,

I have been looking at properties of particles in a simulation, and
sometimes need to match up the particles in two different subsets.  I
typically have (quantity A, index #) for one set of particles, and
(quantity B, index #) for another set, and want to compare quantities
A and B for the particles that are in both sets. 

As of late last night I could not think of a good way to do this;
WHERE inside a for-loop would be very slow.  Maybe I'm missing
something easy, but in any case here's a solution inspired by the
recently submitted SETINTERSECTION function.  Hope somebody finds
it useful.

Mark Fardal
UMass


;+
; NAME: 
;        LISTMATCH
;
; PURPOSE: 
;   find the indices where a matches b
;   works only for SETS OF UNIQUE INTEGERS, e.g., array indices
;
;   for example: suppose you have a list of people with their ages and
;   social security numbers (AGE, AGE_SS), and a partially overlapping
;   list of people with their incomes and s.s. numbers (INCOME,
;   INCOME_SS).  And you want to correlate ages with incomes in the
;   overlapping subset.  Call
;      LISTMATCH, AGE_SS, INCOME_SS, AGE_IND, INCOME_IND
;   then AGE[AGE_IND] and INCOME[INCOME_IND] will be the desired
;   pair of variables.
;
; AUTHOR:
;   Mark Fardal
;   UMass (fardal@weka.astro.umass.edu)
;
; CALLING SEQUENCE:
;   LISTMATCH, a, b, a_ind, b_ind
;   
; INPUTS:
;   a and b are sets of unique integers (no duplicate elements)
; 
; OUTPUTS:
;   a_ind, b_ind are the indices indicating which elements of a and b
;   are in common
;
; RESTRICTIONS:
;   if the indices are not unique some matching elements may be skipped...
;   or is it worse than that?
; EXAMPLE:
;   a = [2,4,6,8]
;   b = [6,1,3,2]
;   listmatch, a, b, a_ind, b_ind
;    print, a[a_ind]
;       2       6
;    print, b[b_ind]
;       2       6
;   
;
; MODIFICATION HISTORY:
;   none
; BUGS:
;   tell me about them
; ACKNOWLEDGEMENTS: 
;   trivial modification of SETINTERSECTION from RSI
;
pro listmatch, a, b, a_ind, b_ind
minab = min(a, MAX=maxa) > min(b, MAX=maxb) ;Only need intersection of ranges
maxab = maxa < maxb
;If either set is empty, or their ranges don't intersect: 
;  result = NULL (which is denoted by integer = -1)
if maxab lt minab or maxab lt 0 then begin
  a_ind = -1
  b_ind = -1
  return
endif

ha = histogram(a, MIN=minab, MAX=maxab, reverse_indices=reva)
hb = histogram(b, MIN=minab, MAX=maxab, reverse_indices=revb)

r = where((ha ne 0) and (hb ne 0), count)
if count gt 0 then begin
  a_ind = reva[reva[r]]
  b_ind = revb[revb[r]]
  return
endif else begin
  a_ind = -1 
  b_ind = -1 
  return
endelse

end