I have created a nice little routine:
(defun unzip (seq)
"Takes an even-length list and breaks it apart by evens/odd index"
(let ((oddresult '())
(evenresult '()))
(loop for n from 0 to (- (length seq) 1) do
(if (oddp n)
(push (nth n seq) oddresult)
(push (nth n seq) evenresult)))
(list (reverse oddresult) (reverse evenresult))))
And to use it:
CL-USER> (unzip '(1 2 3 4 5 6))
((2 4 6) (1 3 5))
However, I am keenly aware of my ability to writebotch C++ in any language, and would like some analysis of my unzip
for good Common Lisp style.
First note that '()
and ()
are equivalent, since empty list is self evaluating and equal to NIL
, and in any case you don't need those in LET because NIL
is implied by `(let (variable) ...) syntax, which is a reason why you need a parenthesis around each binding when giving the a starting value.
Not that using LET
is necessary for this case. Using LOOP features more extensively this function can be written as:
(defun unzip (seq)
"Takes an even-length list and breaks it apart by evens/odd index"
(loop for n from 0
for element in seq
if (oddp n)
collect element into oddresult
else
collect element into evenresult
finally (return (list oddresult evenresult))))
Personally I prefer iterate for most iteration, using which it can be written as:
(defun unzip (seq)
"Takes an even-length list and breaks it apart by evens/odd index"
(iter (for element in seq)
(for n from 0)
(if (oddp n)
(collect element into oddresult)
(collect element into evenresult))
(finally (return (list oddresult evenresult)))))
or even:
(defun unzip (seq)
"Takes an even-length list and breaks it apart by evens/odd index"
(iter (generate element in seq)
(collect (next element) into evenresult)
(collect (next element) into oddresult)
(finally (return (list oddresult evenresult)))))
EDIT: Additional notes: The name unzip
conventionally denotes a slightly different function. The argument name should really be list
, since seq
would suggest the the function also takes vectors. While it is possible to have functions operating on generalized sequences, it is usually not recommended, since lists and vectors have different performance characteristics. In particular, random access through NTH
is linear time for lists, which means you should almost never use it. Even if the time cost is insignificant it usually indicates you should be using a different datastructure.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With