I'll add my 2 cents to the discussion.
Dealing with two lists is easy.
One way was described by MP but keep in mind that the member or vl-position functions
do not preform well with real numbers because of rounding. Slight variations will cause
them to fail to find a match. Dealing with real numbers you need to use equal with a fuzz
or use the distance function when dealing with point lists.
Example:
_$ (equal '(585.039 339.407) '(585.039 339.407))
T
_$ (equal '(585.03901 339.407) '(585.039 339.407))
nil
_$ (equal '(585.03901 339.407) '(585.039 339.407) 0.0001)
T
There is another potential problem using
foreachfunction. When the
foreachfunction is
initialized the list is placed in another hidden variable or memory location and is not bound
to the original list. If you alter the list within the
foreachconstruct the change will not
be evident to the
foreachfunction.
Example:
(setq lst '(1 2 3 4 5))
(foreach itm lst
(if (= itm 2)
(setq lst (reverse (cdr (reverse lst))))
)
(print itm) (princ " - ")(princ lst)
)
(princ)
You see although lst was changed to 4 items the
foreachdid 5 iteration's.
Comparing two lists of point lists you might want to use nested
foreachfunctions.
(defun c:test (/ lst1 lst2 p1 p2 matchList)
(setq lst1 '((546.541 279.55) ; 2D point list
(585.039 339.407)
(540.008 394.517)
(473.68 368.72)
(477.717 297.667)
)
)
(setq lst2 '((546.541 279.55 12.5) ; 3D point list
(585.039 339.407 15.6)
(540.008 394.517 22.7)
)
)
(defun 2d (pt) ; return a point list less the Z value
(list (car pt) (cadr pt))
)
(foreach p1 lst1
(foreach p2 lst2
(if (equal (2d p1) (2d p2) 0.0001)
(setq matchList (cons p2 matchList))
)
)
)
(print matchList)
(princ)
)
You can see that lst2 is iterated each time an item in lst1 is processed.
With large lists it may be desirable to remove a point from lst2 when it is paired.
To accomplish this the use of a
while function does the job. The
while function
will not store the list value and therefore your change will shorten the processing.
(defun c:test (/ lst1 lst2 p1 p2 idx matchList tmplst)
(setq lst1 '((546.541 279.55) ; 2D point list
(585.039 339.407)
(540.008 394.517)
(473.68 368.72)
(477.717 297.667)
)
)
(setq lst2 '((546.541 279.55 12.5) ; 3D point list
(585.039 339.407 15.6)
(540.008 394.517 22.7)
)
)
(defun 2d (pt) ; return a point list less the Z value
(list (car pt) (cadr pt))
)
(foreach p1 lst1
(setq tmplst lst2)
(while (setq p2 (car tmplst))
(setq tmplst (cdr tmplst))
(if (equal (2d p1) (2d p2) 0.0001)
(setq matchList (cons p2 matchList)
lst2 (vl-remove p2 lst2))
)
)
)
(print matchList)
(princ)
)
You can also use a pointer with the
while loop.
(defun c:test (/ lst1 lst2 p1 p2 idx matchList)
(setq lst1 '((546.541 279.55) ; 2D point list
(585.039 339.407)
(540.008 394.517)
(473.68 368.72)
(477.717 297.667)
)
)
(setq lst2 '((546.541 279.55 12.5) ; 3D point list
(585.039 339.407 15.6)
(540.008 394.517 22.7)
)
)
(defun 2d (pt) ; return a point list less the Z value
(list (car pt) (cadr pt))
)
(foreach p1 lst1
(setq idx (length lst2))
(while (>= (setq idx (1- idx)) 0)
(setq p2 (nth idx lst2))
(if (equal (2d p1) (2d p2) 0.0001)
(setq matchList (cons p2 matchList)
lst2 (vl-remove p2 lst2))
)
(print lst2)
)
)
(print matchList)
(princ)
)
You may wonder why the vl-remove works with point data, real numbers.
That only works because p2 is an exact copy of the data found in lst2.
That's it.