如何比较lisp中长度或结构不完全相同的两个列表?

时间:2012-03-06 04:29:44

标签: loops lisp common-lisp

我有这两个清单:

'(and 1 (or a b))
'( (a 0)(b 1) )

我是lisp的新手,我发现很难弄清楚如何比较这两个列表。我正在考虑创建一个比较函数,但我不知道如何逐个比较它们,因为在评估表达式之前不会返回lisp值。由于它们也不是相同的结构,我不能假设它们在结构上至少是相同的。任何解释如何工作?

编辑:抱歉,我忘了说为什么要比较。第二个列表是假设将数字绑定到第一个列表中存在这些变量的所有位置。因此得到的第一个列表应该是:

'(and 1(or 0 1))

2 个答案:

答案 0 :(得分:3)

内置:

$ clisp -q
[1]> (sublis '((a . 0) (b . 1)) '(and 1 (or a b)))
(AND 1 (OR 0 1))
[2]> 

因此,家庭作业减少为SUBLIS的包装器,它接受形式的结合((a 0)(b 1))而不是((a。0)(b.1))。

线索:

(loop for (x y) in vars collecting (cons x y))

答案 1 :(得分:0)

;;; Look up a var like A a list like ((A 0) (B 1))
;;; and retrieve the (A 0). Or nil if not found.
(defun lookup-var (var bindings)
  (find var bindings :key #'first))

;;; The homework
(defun subst-vars (tree bindings)
  (cond
    ;; if the tree is a cons cell, then substitute in the
    ;; car, substitute in the cdr, and combine the results by consing
    ;; a new cons! Easy!
    ((consp tree) (cons (subst-vars (car tree) bindings)
                        (subst-vars (cdr tree) bindings)))
    ;; Otherwise the tree must be an atom. See if the atom is
    ;; a var that we can substitute. If not, return the atom.
    (t (let ((binding (lookup-var tree bindings)))
         (if binding
           (second binding) ;; got a binding entry; return its value!
           tree)))))            ;; no deal, just return the original

在stackoverflow窗口中键入此内容,它在没有编辑的情况下运行。 :)

但这是非常低效的。假设变量根本不在树中发生。它使得树的浪费副本而不仅仅是返回树。所以你自己做了一些工作,你能想出一种方法来优化它,以避免不必要地调用cons函数吗?提示:检查对subst-vars的递归调用是否只返回相同的对象。