我熬夜写这个函数,它接受一个字符串列表并将其转换为一组递归嵌套的alist。我尝试使用pushnew,以便现有的字符串不会重复,但必须创建我自己的重复测试,因为我无法得到pushnew。
显然有一种方法可以使用递归,但是我无法使用它,因为我无法将pushnew的目标部分调用到正确的位置。
我终于以一种愚蠢的方式做到了,但是聪明的方式是什么?
(defvar vocab '())
(defun place-down ( a b &optional c d e f g)
(unless (assoc a vocab :test #'equal)
(pushnew (cons a '()) vocab :test #'equal))
(unless (assoc b (cdr(assoc a vocab :test #'equal)):test #'equal)
(pushnew (cons b '()) (cdr(assoc a vocab :test #'equal :test #'equal))))
(when c
(unless (assoc c (cdr(assoc b (cdr(assoc a vocab :test #'equal :test #'equal
)):test #'equal)):test #'equal)
(pushnew (cons c '()) (cdr(assoc b (cdr(assoc a vocab :test #'equal
:test #'equal)):test #'equal)))))
(when d
(unless (assoc d (cdr(assoc c (cdr(assoc b (cdr(assoc a vocab :test #'equal
:test #'equal)):test #'equal)):test #'equal)):test #'equal)
(pushnew (cons d '()) (cdr(assoc c (cdr(assoc b (cdr(assoc a vocab :test
#'equal :test #'equal)):test #'equal)):test #'equal)))))
(when e
(unless (assoc e (cdr(assoc d (cdr(assoc c (cdr(assoc b (cdr(assoc a vocab
:test #'equal :test #'equal)) :test #'equal)):test #'equal)):test #'equal)):test #'equal)
(pushnew (cons e '()) (cdr(assoc d (cdr(assoc c(cdr(assoc b (cdr(assoc a vocab
:test #'equal :test #'equal)) :test #'equal)):test #'equal)):test #'equal)))))
(when f
(unless (assoc f (cdr(assoc e (cdr(assoc d(cdr(assoc c(cdr(assoc b (cdr(assoc a vocab
:test #'equal :test #'equal)) :test #'equal)):test #'equal)):test #'equal)):test #'equal))
:test #'equal)
(pushnew (cons f '()) (cdr(assoc e (cdr(assoc d(cdr(assoc c(cdr(assoc b (cdr(assoc a vocab
:test #'equal :test #'equal)) :test #'equal)):test #'equal)):test #'equal)):test #'equal)))))
(when g
(unless (assoc g (cdr(assoc f (cdr(assoc e(cdr(assoc d(cdr(assoc c(cdr(assoc b (cdr(assoc a vocab
:test #'equal :test #'equal)) :test #'equal)):test #'equal)):test #'equal)):test #'equal))
:test #'equal)):test #'equal)
(pushnew (cons g '()) (cdr(assoc f (cdr(assoc e(cdr(assoc d(cdr(assoc c(cdr(assoc b (cdr(assoc a vocab
:test #'equal :test #'equal)) :test #'equal)):test #'equal)):test #'equal)):test #'equal)):test #'equal))))))
在我说的那些:
*(place-down "this" "is" "it" "the" "life" "we" "live")
* vocab
=> (("this" ("is" ("it" ("the" ("life" ("we" ("live"))))))))
答案 0 :(得分:3)
示例看起来像REDUCE
可以解决的问题。
(defun place-down (&rest strings)
(reduce (lambda (string accumulator)
(if accumulator
(list string accumulator)
(list string)))
strings
:initial-value nil
:from-end t))
具有显式REDUCE
参数的 :initial-value
是以最统一的方式调用给定的reduce函数的情况;否则,该函数可以用零或两个参数调用,如果列表只有一个元素,甚至根本不能调用(谢谢@jkiiski)。如果累加器是NIL,我们将其丢弃。测试:
(place-down "this" "is" "it" "the" "life" "we" "live")
=> ("this" ("is" ("it" ("the" ("life" ("we" ("live")))))))
(place-down "this" "is" "it")
=> ("this" ("is" ("it")))
(place-down "this")
=> ("this")
(place-down)
=> NIL
:from-end t
参数使操作成为右关联。
答案 1 :(得分:1)
CL-USER 8 > (loop with result = nil
for l in (reverse '("this" "is" "it" "the" "life" "we" "live"))
do (setf result (list (cons l result)))
finally (return result))
(("this" ("is" ("it" ("the" ("life" ("we" ("live"))))))))
或
CL-USER 9 > (let ((result nil)
(list '("this" "is" "it" "the" "life" "we" "live")))
(dolist (l (reverse list) result)
(setf result (list (cons l result)))))
(("this" ("is" ("it" ("the" ("life" ("we" ("live"))))))))