【问题标题】:How to compare two lists in lisp that are not exactly the same in length or structure?如何比较 lisp 中长度或结构不完全相同的两个列表?
【发布时间】:2012-03-06 04:29:43
【问题描述】:

我有这两个列表:

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

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

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

'(and 1(or 0 1))

【问题讨论】:

  • 如果您不知道如何指定解决方案的结构,您将无法编写代码。如果您手动比较以上两个列表,结果应该是什么?内置的 EQUAL 函数将返回 NIL,因为它们是不同的列表。
  • 我刚加了,不好意思一开始没加
  • 实际的作业问题是什么?
  • 我明白了。好吧,这不是比较;那就是替代!您应该在第一个列表中实例化第二个列表中指定的变量。 CL 中有一个 SUBLIS 函数可以做到这一点。
  • 哦,我明白了!我只是想靠自己来理解 lisp 控制结构。但它真的很难想象这将如何工作。我研究了这个功能,但如果我要自己尝试做,我怎么能做到呢?

标签: loops lisp common-lisp


【解决方案1】:

内置:

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

【讨论】:

  • 谢谢你的例子!非常感谢!
  • 我不确定是否会接受基于 SUBLIS 的解决方案作为作业。但这是老师的错。让学生实现琐碎的功能在教学中是合适的,而不是 Lisp。 :)
【解决方案2】:
;;; 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 的递归调用是否只返回相同的对象。

【讨论】:

    猜你喜欢
    • 2021-02-25
    • 1970-01-01
    • 2017-12-24
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多