如何从lisp中的字符串列表创建递归嵌套的Alist

如何从lisp中的字符串列表创建递归嵌套的Alist,lisp,common-lisp,Lisp,Common Lisp,我整晚都在写这个函数,它获取字符串列表并将其转换为一组递归嵌套的alist。我尝试使用pushnew,这样现有的字符串就不会被复制,但我必须创建自己的重复测试,因为我不能让pushnew来做 显然有一种方法可以使用递归,但我无法使其工作,因为我无法正确调用pushnew的目标部分 我终于用了一种愚蠢的方式,但什么是聪明的方式呢 (defvar vocab '()) (defun place-down ( a b &optional c d e f g) (unless

我整晚都在写这个函数,它获取字符串列表并将其转换为一组递归嵌套的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"))))))))

这个例子似乎可以解决问题

(defun place-down (&rest strings)
  (reduce (lambda (string accumulator)
            (if accumulator
                (list string accumulator)
                (list string)))
          strings
          :initial-value nil
          :from-end t))
使用显式REDUCE:初始值参数是以最统一的方式调用给定的REDUCE函数的情况;否则,可以使用零或两个参数调用该函数,如果列表中只有一个元素,甚至根本无法调用该函数。谢谢@jkiiski。如果累加器为零,则丢弃它。测试:

(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参数使操作右关联。

该示例似乎可以解决一些问题

(defun place-down (&rest strings)
  (reduce (lambda (string accumulator)
            (if accumulator
                (list string accumulator)
                (list string)))
          strings
          :initial-value nil
          :from-end t))
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"))))))))
使用显式REDUCE:初始值参数是以最统一的方式调用给定的REDUCE函数的情况;否则,可以使用零或两个参数调用该函数,如果列表中只有一个元素,甚至根本无法调用该函数。谢谢@jkiiski。如果累加器为零,则丢弃它。测试:

(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参数使操作右关联

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"))))))))


您忘记了REDUCE的另一个特例;当只使用一个元素调用输入时,它将按原样返回元素。在这种情况下,我假设单独的元素仍然应该包装在一个列表中。谢谢,我将研究这个reduce。我发现Lisp是令人兴奋的、强大的、独特的、深不可测的。感谢you@jkiiski非常感谢你抓住了这一点,你忘记了另一个减少的特殊情况;当只使用一个元素调用输入时,它将按原样返回元素。在这种情况下,我假设单独的元素仍然应该包装在一个列表中。谢谢,我将研究这个reduce。我发现Lisp是令人兴奋的、强大的、独特的、深不可测的。感谢you@jkiiski非常感谢你能理解我的话。谢谢你,但我问对了问题,但做得很差。假设我已经有了一个嵌套信息树,并且我想向其中添加一个函数。它可以采取这就是我们的生活,并检查是否有,如果有必要添加它。也许这就是它已经存在于树上的原因。这是最高级别。该函数沿着它向下,在不重复前三个单词的情况下,将我们生活的生活添加到正确的位置。@GreggArthurEvans:您仍然可以使用循环或递归调用遍历现有的树。在您的示例中不需要代码重复。谢谢,当我们可以计算某个位置或传递某个位置而不是副本时,在lisp中调用什么?我正试图找出这个函数的规则,因为这就是我在这个函数中遇到的问题。天哪,鲭鱼!!!乔斯威格先生。我是通过弄乱你的例子才弄明白的。非常感谢你!谢谢,但我问对了问题,做得很差。假设我已经有了一个嵌套信息树,并且我想向其中添加一个函数。它可以采取这就是我们的生活,并检查是否有,如果有必要添加它。也许这就是它已经存在于树上的原因。这是最高级别。该函数沿着它向下,在不重复前三个单词的情况下,将我们生活的生活添加到正确的位置。@GreggArthurEvans:您仍然可以使用循环或递归调用遍历现有的树。在您的示例中不需要代码重复。谢谢,当我们可以计算某个位置或传递某个位置而不是副本时,在lisp中调用什么?我正试图找出这个函数的规则,因为这就是我在这个函数中遇到的问题。天哪,鲭鱼!!!乔斯威格先生。我是通过弄乱你的例子才弄明白的。非常感谢你!