42087
42087

Reputation: 39

Adding List Items together

I have a list and I want to add/concatenate the elements.

((a b) (c d) (e f)) -> ((a b c d) (a b e f) (c d e f))

This is what it should look like. The List ist never of fixed size, so it could also just be two elements or more than three. I've tried using a loop, but that returns a lot of extra lists I don't want.

(setq a '((a b) (c d) (e f))
(setq b '((a b) (c d) (e f))
(loop for x in a
              append (loop for y in b
                           collect (append x y)))

Result :

((A B A B) (A B C D) (A B E F) (C D A B) (C D C D) (C D E F) (E F A B) (E F C D) (E F E F))

Is there a way to limit the loop? Or is there a better way than using a loop at all? I don't know how this would be called so I'm not able to find any answers to my problem.

Upvotes: 1

Views: 114

Answers (1)

Silvio Mayolo
Silvio Mayolo

Reputation: 70277

You want to concatenate each element of the list with each element of the tail of the list from that point. To get all of the tails of a list, we use the loop keyword on rather than in.

(loop for (x . tail) on a
      append (loop for y in tail
                   collect (append x y)))

Using on rather than in in the first loop makes the loop variable be equal to the cons cells, not just their car. So whereas your original outer loop would produce the values

(a b)
(c d)
(e f)

My outer loop will produce

((a b) (c d) (e f))
((c d) (e f))
((e f))

Then we immediately destructure it, so x will be the elements of the list and tail, at each iteration, will be the rest of the list after that point, i.e. the exact thing we want to iterate over in our inner loop. Everything else is exactly as you already figured out.


All of the obscure loop constructs can be a bit obtuse to figure out. I have found that the best reference is this chapter from the Practical Common Lisp book (the entire book is available online for free and I highly recommend it for folks learning Lisp)

Upvotes: 3

Related Questions