检查正确的子集

时间:2013-09-22 20:01:58

标签: lisp common-lisp subset

我需要一个能够检查列表a是否是列表b的正确子集的函数。到目前为止我的代码是:

(defun proper-subset (a b)
    (cond
    (( or (null b)(null b)) nil)
    ((equal a b) nil)
    ((find (car a) b) (proper-subset (cdr a) b))
   )
)

find会检查a的每个元素是否在b中。我知道null参数也需要一些工作,但我想弄清楚如何确定ab的每个元素何时找到,b有另一个元素。有内置的功能可以使这更容易,但这是一个功课问题所以我必须自己编写。任何提示或建议将不胜感激。

2 个答案:

答案 0 :(得分:3)

Common Lisp定义了许多用于将列表作为集合处理的函数,因此您不需要编写自己的函数。特别是,有用的函数出现在The Conses Dictionary的底部。特别有用的是

subsetp 几乎做你想要的,但它正在检查不正确的子集。但是,请注意您可以使用这些函数来计算所需的内容。最直接的方法是检查 A B 的子集,以及 B - A≠{} 。这符合您的描述,“a的每个元素都在b和b中找到了另一个元素”。

(defun proper-subsetp (a b)
  (and (subsetp a b)                       ; every element of a is found in b
       (not (endp (set-difference b a))))) ; b has another element
CL-USER> (proper-subsetp '(1 2 3) '(1 2 3 4))
T
CL-USER> (proper-subsetp '(1 2 3 4) '(1 2 3 4))
NIL

由于这些函数实际上采用了一些参数,可以让您确定元素的比较方式。您可以使用&rest参数添加这些参数并应用:

(defun proper-subsetp (a b &rest keys)
  (and (apply 'subsetp a b keys )
       (not (endp (apply 'set-difference b a keys)))))

使用它,你可以,而不是直接比较元素,比较它们的长度:

CL-USER> (proper-subsetp '("a" "bb" "ccc") '("1" "22" "333") :key 'length)
NIL
CL-USER> (proper-subsetp '("a" "bb" "ccc") '("1" "22" "333" "4444") :key 'length)
T

答案 1 :(得分:0)

以下只会将if添加到您提到的操作集中,但这实际上是一种非常糟糕的方式。如果这就是他们教给你的东西(你没有自愿参加)。现在是时候你会得到一本关于Lisp的好书并自己研究一下。在我看来,这个练习毫无意义。

(defun purge (element from-list)
  (if (null from-list) nil
      (if (equal element (car from-list))
          (purge element (cdr from-list))
          (cons (car from-list) (purge element (cdr from-list))))))

(defun proper-subset-p (suspect of)
  (if (null suspect) (not (null of))
      (if (not (equal (purge (car suspect) of) of))
          (proper-subset-p
           (purge (car suspect) suspect)
           (purge (car suspect) of)) nil)))

同样的事情,但cond

(defun purge (element from-list)
  (cond
    ((null from-list) nil)
    ((equal element (car from-list)) (purge element (cdr from-list)))
    (t (cons (car from-list) (purge element (cdr from-list))))))

(defun proper-subset-p (suspect of)
  (cond
    ((null suspect) (not (null of)))
    ((not (equal (purge (car suspect) of) of))
     (proper-subset-p (purge (car suspect) suspect) (purge (car suspect) of)))
    (t nil)))