lisp - 稳定联合 lisp

标签 lisp

需要在 lisp 中编写一个联合函数,它将两个列表作为参数并返回一个列表,该列表是两个列表的并集,没有重复。顺序应与输入列表的顺序一致

例如:如果输入是'(a b c)和'(e c d),结果应该是'(a b c e d)

这是我目前的情况

(defun stable-union (x y)
  (cond
   ((null x) y)
   ((null y) x))
  (do ((i y (cdr i))
       (lst3 x (append lst3 
                       (cond
                        ((listp i) 
                         ((null (member (car i) lst3)) (cons (car i) nil) nil))
                        (t (null (member i lst3)) (cons i nil) nil)))))
        ((null (cdr i)) lst3)))

我的错误是存在一个“非法函数对象”,段为 (null (member (car i) lst3))

建议?

最佳答案

你把你的 parent 弄得一团糟:

(defun stable-union (x y)
  (cond
   ((null x) y)
   ((null y) x)  )     END OF COND form - has no effect

  (do ((i y (cdr i))
      ^^
       (lst3 x (append lst3 
                       (cond
                        ((listp i) 
                         (  (null (member (car i) lst3)) 
                         ^^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ called as a function
                             (cons (car i) nil)           with two arguments
                             nil  ) )
                                 ^^ 
                        (t                         NEXT 3 forms have no effect
                           (null (member i lst3))
                           (cons i nil)
                           nil           )))) )
                                             ^^
        ((null (cdr i)) lst3)))

这是您可能想要的代码,其中包含更正的括号并在需要的地方添加了一些 if:

(defun stable-union (x y)
  (cond
   ((null x) y)
   ((null y) x)
   (t
    (do ((i y (cdr i))
         (lst3 x (append lst3 
                   (cond
                     ((listp i) 
                       (if (null (member (car i) lst3))
                           (cons (car i) nil)
                           nil))
                     (t 
                       (if (null (member i lst3))
                           (cons i nil)
                           nil))))))
        ((null (cdr i)) lst3)))))

这段代码还有问题。您的 do 逻辑是错误的,如果它只包含一个元素,它会跳过 y 中的第一个元素。而且无论是否需要,您都会一直调用 append。请注意,调用 (append lst3 nil) 会复制 lst3 中的顶级 cons 单元格,这完全是多余的。

像你这样的长语句通常放在 do 主体中,而不是放在 do 的局部变量的更新表单中。


但是您可以在适当的地方使用更特殊形式的do。这里自然要用到dolist。正在关注"wvxvw"'s lead on using hash-tables for membership testing ,我们写:

(defun stable-union (a b &aux (z (list nil)))
  (let ((h (make-hash-table))
        (p z))
    (dolist (i a)
      (unless (gethash i h)
        (setf (cdr p) (list i) p (cdr p))
        (setf (gethash i h) t)))
    (dolist (i b (cdr z))
      (unless (gethash i h)
        (setf (cdr p) (list i) p (cdr p))
        (setf (gethash i h) t)))))

使用一种我称之为“head-sentinel”的技术(z 变量预初始化为单例列表)允许以一定的成本极大地简化自上而下列表构建的代码分配一个额外的 cons 单元格。

关于lisp - 稳定联合 lisp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12847764/

相关文章:

list - 理解 SICP 中的树 - 练习 2.24

emacs - 如何在elisp中使用过滤器执行sudo命令

list - 方案:返回一个表达式的所有元素,可以使用car和cdr的任意组合得到

lisp - 在 Common Lisp 的 Progn 中加载包

recursion - 检查二叉树是否为二叉搜索树的 Lisp 程序

lisp - lambda 可以有文档字符串吗?

emacs - 在 Vista 上的 slime 下启动 sbcl 时出错

xml - 在 common lisp 中处理 http 请求和 xml

algorithm - 无休止地添加到 lisp 中的合并排序列表

macros - let* 和 set 的区别?在普通 Lisp 中