Page 1 of 1

iterating through the same list with two indices

Posted: Thu Mar 01, 2012 10:55 am
I need to run through a list comparing each member to every member after that member for a condition. A very naiive approach would be:

Code: Select all

(loop for i from 0 to (1- (length THE-LIST)) do
   (loop for j from (1+ i) to (1- (length THE-LIST)) do
      (test-the-items  (nth i THE-LIST) (nth j THE-LIST))
This is easily understood, but very ugly.

Another lispier, but probably just as ugly, way would be

Code: Select all

(mapcar #'(lambda (item1)
                     (mapcar #'(lambda (item2) 
                                         (test-the-items item1 item2))
                                  (nthcdr (position item1 THE-LIST))))  THE-LIST)
Is there a cleaner way to do this?

Edit, after some more thinking, this:

Code: Select all

    
(loop for i in THE-LIST do
	  (loop for j in (nthcdr (1+ (position i THE-LIST)) THE-LIST) do
                 (test-the-items i j))

Re: iterating through the same list with two indices

Posted: Thu Mar 01, 2012 3:05 pm
by gugamilare
I don't think the solution with MAPCAR is ugly at all, it's only verbose, but lispy at the same time

Another option would be:

Code: Select all

(loop for (elt1 . rest) on THE-LIST do
     (loop for elt2 in rest do
          (test-the-items elt1 elt2)))

Re: iterating through the same list with two indices

Posted: Thu Mar 01, 2012 3:28 pm
gugamilare wrote:I don't think the solution with MAPCAR is ugly at all, it's only verbose, but lispy at the same time

Another option would be:

Code: Select all

(loop for (elt1 . rest) on THE-LIST do
     (loop for elt2 in rest do
          (test-the-items elt1 elt2)))
That dotted list is perfect, it is easy to understand and efficient. Thanks!

Re: iterating through the same list with two indices

Posted: Mon Mar 05, 2012 3:26 pm
by wvxvw
Just a side note:

Code: Select all

to (1- (length THE-LIST))
is equivalent to:

Code: Select all

below (length THE-LIST)