Reputation: 39
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
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