0

我必须这样做:

(or a w (or f r t) r (not p) (or (not p) a))

==> (a w f r t r (not p) (not p) a)

我已经完成了这个功能:

(defun remove-or (x)
  (cond ((null x) x)
    ((atom x) x)
    ((and (listp x) (eq (first x) 'or)) (remove-or (cdr x)))
    (T (cons (remove-or (first x))
             (remove-or (rest x))))))

但结果是:

(or a w (or f r t) r (not p) (or (not p) a))

==> (a w (f r t) r (not p) ((not p) a))

如何删除“()”?

4

1 回答 1

0

您需要提前检查或子列表,例如 '((or ...) ...),以便您可以将其转换为 '(... ...)。

它的条件很简单:

(and (listp lst) (listp (first lst))
     (eq (first (first lst)) 'or))

还有变压器:

(append (remove-or (rest (first lst)))
        (remove-or (rest lst)))

因此,这将我们带到了您的函数,其中第三个条件分支略有修改:

(defun remove-or (lst)
  (cond ((null lst) lst)
        ((atom lst) lst)
        ((and (listp lst) (listp (first lst))
              (eq (first (first lst)) 'or))
         (append (remove-or (rest (first lst)))
                 (remove-or (rest lst))))
        (t (cons (remove-or (first lst))
                 (remove-or (rest lst))))))

但是这个函数不会处理一种特殊情况:列表最开始的 or :(OR ab(或(或 cd)e))。但是有一个额外的条件分支,像((and (listp x) (eq (first x) 'or)) (remove-or (cdr x)))我们将删除or的 s 也像变量一样:(abc)。

所以这种情况必须分开处理,例如:

(defun remove-or-head (lst)
   (remove-or (if (and (listp lst) (eq (first lst) 'or))
                  (rest lst)
                  lst))

将它们与隐藏的递归函数放在一起:

(defun remove-or (lst)
  (labels ((remove-or-rec (lst)
             (cond ((null lst) lst)
                   ((atom lst) lst)
                   ((and (listp lst) (listp (first lst))
                         (eq (first (first lst)) 'or))
                    (append (remove-or-rec (rest (first lst)))
                            (remove-or-rec (rest lst))))
                   (t (cons (remove-or-rec (first lst))
                          (remove-or-rec (rest lst)))))))
    (remove-or-rec (if (and (listp lst) (eq 'or (first lst)))
                       (rest lst)
                       lst))))
于 2013-02-02T14:14:09.333 回答