假设您有一个列表,并希望生成所有有序元素对的列表,例如列表是’(1 3 5 7 9),所需的结果是
((1.1)(1.3)(1.5)(1.7)(1.9)(3.3)(3.5)(……
的 通过使用 map 仅限家庭功能 强>
map
在我看来,这是非常lispy(也许是一个解决方案 loop -haters):
loop
(defun 1st-conses (l) (mapcar #'(lambda (x) (cons (car l) x)) l)) (mapcan #'1st-conses (maplist #'identity '(1 3 5 7 9)) ;; ((1 . 1) (1 . 3) (1 . 5) (1 . 7) (1 . 9) (3 . 3) (3 . 5) (3 . 7) (3 . 9) ;; (5 . 5) (5 . 7) (5 . 9) (7 . 7) (7 . 9) (9 . 9))
的 仅通过递归 强>
和尾部调用递归解决方案 loop -haters:
(defun 1st-conses (l) (labels ((.1st-conses (l fst acc) (cond ((null l) (nreverse acc)) (t (.1st-conses (cdr l) fst (cons (cons fst (car l)) acc)))))) (.1st-conses l (car l) '()))) (defun combine-down (l &optional (acc '())) (cond ((null l) acc) (t (pairing-down (cdr l) (nconc acc (1st-conses l)))))) (combine-down '(1 3 5 7 9)) ;; ((1 . 1) (1 . 3) (1 . 5) (1 . 7) (1 . 9) (3 . 3) (3 . 5) (3 . 7) (3 . 9) ;; (5 . 5) (5 . 7) (5 . 9) (7 . 7) (7 . 9) (9 . 9))
的 小 loop 功能 强>
这三个函数的融合版本在其他答案中给出:
(defun tails (l) (loop for x on l collect x)) (defun 1st-conses (l) (loop for x in l collect (cons (car l) x))) (loop for l in (tails '(1 3 5 7 9)) nconc (1st-conses l))
的 具有小功能的更通用解决方案 强>
结合这三个功能中的任何一个 - 每个功能都带有一个 map -version,a loop -version和尾调用递归版本。 - 所以你可以选择创建一个
或者您
功能是:
;;;;;;;;;;;;;;;;;;;; ;; function collecting all `cdr`s of a list: ;; (tails '(a b c)) ;; ;; returns: ((A B C) (B C) (C)) ;;;;;;;;;;;;;;;;;;;; ;; with `map`s (defun tails (l) (maplist #'identity l)) ;; with `loop` (defun tails (l) (loop for x on l collect x)) ;; tail-call-recursion (defun tails (l &optional (acc '())) (cond ((null l) (nreverse acc)) (t (tails (cdr l) (cons l acc))))) ;;;;;;;;;;;;;;;;;;;; ;; function collecting `car` of a list `cons`ed with each list element ;; (1st-conses '(a b c)) ;; ;; returns: ((A . A) (A . B) (A . C)) ;;;;;;;;;;;;;;;;;;;; ;; with `map`s (defun 1st-conses (l) (mapcar #'(lambda (x) (cons (car l) x)) l)) ;; with `loop` (defun 1st-conses (l) (loop for x in l collect (cons (car l) x))) ;; tail-call-recursion (defun 1st-conses (l) (labels ((.1st-conses (l fst acc) (cond ((null l) (nreverse acc)) (t (.1st-conses (cdr l) fst (cons (cons fst (car l)) acc)))))) (.1st-conses l (car l) '()))) ;;;;;;;;;;;;;;;;;;;; ;; applying the second function on the first functions' results ;; (combine-down '(a b c)) ;; ;; returning: ((A . A) (A . B) (A . C) (B . B) (B . C) (C . C)) ;;;;;;;;;;;;;;;;;;;; ;; with `map`s (defun combine-down (l) (mapcan #'1st-conses (tails l))) ;; with `loop` (defun combine-down (l) (loop for x in (tails l) nconc (1st-conses x))) ;; with tail-call-recursion (defun combine-down (l) (labels ((.combine-down (l acc) (cond ((null l) acc) (t (.combine-down (cdr l) (nconc acc (1st-conses (car l)))))))) (.combine-down (tails l) '())))
然后:
(combine-down '(1 3 5 7 9)) ;; ((1 . 1) (1 . 3) (1 . 5) (1 . 7) (1 . 9) (3 . 3) (3 . 5) (3 . 7) (3 . 9) ;; (5 . 5) (5 . 7) (5 . 9) (7 . 7) (7 . 9) (9 . 9))
的 势在必行 强>
为了好玩,我尽可能地翻译了命令式cpp代码 - 因为作为一种真正的多范式语言...:
(let ((arr '(1 3 5 7 9)) (res '())) (loop for i from 0 below 5 by 1 do (loop for j from i below 5 by 1 do (setq res (cons (cons (elt arr i) (elt arr j)) res)))) (nreverse res))
它正确返回:
((1 . 1) (1 . 3) (1 . 5) (1 . 7) (1 . 9) (3 . 3) (3 . 5) (3 . 7) (3 . 9) (5 . 5) (5 . 7) (5 . 9) (7 . 7) (7 . 9) (9 . 9))