转置列表清单很简单,但需要注意的是,您不得超过call-arguments-limit
。
http://www.lispworks.com/kb/4fbc798cb17237ca852566da005fcc79.html
当列表长度超过call-arguments-limit
时,什么是一种安全的移调方式?
例如,答案不是这一个:https://stackoverflow.com/a/3513158/914859
(defun transpose (list-of-lists)
(apply #'mapcar #'list list-of-lists))
答案 0 :(得分:5)
这是一个不受阻碍的非递归版本
由call-arguments-limit
等人:
(defun pop-all (list-of-lists)
"Pop each list in the list, return list of pop results
and an indicator if some list has been exhausted."
(loop for tail on list-of-lists collect (pop (car tail))))
(defun transpose (list-of-lists)
"Transpose the matrix."
(loop with tails = (copy-list list-of-lists)
while (some #'consp tails) ; or any?
collect (pop-all tails)))
测试:
(defparameter ll '((1 4 7) (2 5 8) (3 6 9)))
(transpose ll)
==> ((1 2 3) (4 5 6) (7 8 9))
ll
==> ((1 4 7) (2 5 8) (3 6 9))
(equal ll (transpose (transpose ll)))
==> T
请注意,我每次扫描list-of-lists
两次 - 一次在some
,一次在pop-all
(与similar answer相同)。
我们可以通过一些额外的工作来避免它:
(defun pop-all (list-of-lists)
"Pop each list in the list, return list of pop results
and an indicator if some list has been exhausted."
(loop for tail on list-of-lists
for more = (consp (car tail)) then (and more (consp (car tail)))
collect (pop (car tail)) into card
finally (return (values cars more))))
(defun transpose (list-of-lists)
"Transpose the matrix."
(loop with tails = (copy-list list-of-lists) and more and cars
do (setf (values cars more) (pop-all tails))
while more collect cars))