5

我想编写一个函数,它将两个列表作为参数,并检查第一个列表中的每个元素是否都包含在第二个列表中(元素的顺序无关紧要)。该函数还将检查两个列表是否具有相同的长度(两个列表不能有重复的元素),因为如果不是,则该函数将返回 nill/false。

例如: (ABCDEF) 和 (BEAFDC) 具有相同的元素 (nil) 和 (nil) 具有相同的元素

(ABCDEF) 和 (ABCDEFG) 没有相同的元素

问题是我只知道一些基本命令,我只能使用那些。这些几乎是我知道的所有命令:

CAR, CDR, LENGTH, NULL, MEMBER, NOT, AND, OR, NOT, MAPCAR, APPLY, DO, SETQ, LET

到目前为止,我编写了以下函数,但我不知道如何检查重复成员,并且它不适用于我要检查的所有列表:

(defun same-elem-p (lst1 lst2)
  (cond ((not (null lst1))
         (cond ((member (car lst1) lst2)
                (same-elem-p (cdr lst1) lst2))
               (t nil)))
        (t t))) 

我希望我能很好地解释这个问题。

4

7 回答 7

5

您可以定义一个在列表包含另一个列表时返回 true 的函数:

(defun member (x liste) 
   (cond
      ((null liste) ()) 
      ((equal (car liste) x) liste) 
      (t (member x (cdr liste))))) 

(defun inclus (liste1 liste2) 
   (cond 
      ((null liste1) t) 
      ((member (car liste1) liste2)(inclus (cdr liste1) liste2)) 
      (t ()))) 

然后用它来判断两个列表是否相等:

(defun compare (liste1 liste2)
   (if ((and (inclus liste1 liste2) (inclus liste2 liste1)))
      (print "the 2 lists are equivalent")
      (print "the 2 lists aren't equivalent"))) 
于 2013-04-02T10:40:06.593 回答
2

当一个列表中的每个元素都是另一个列表的成员时,两个列表具有相同的元素,反之亦然。假设您可以使用该every功能,一个快速的测试方法如下:

(defun same-elements (lst1 lst2)
  (and (= (length lst1) (length lst2))
       (every #'(lambda (x) (member x lst2))
                lst1)
       (every #'(lambda (x) (member x lst1))
                lst2)))

例如:

CL-USER> (same-elements '(a b c) '(c a b))
T

请注意,此代码不会处理所有情况。例如,T当两个不同的元素在两个列表中重复时,它会返回,如(a b b c)(a a b c)。但是,在大多数情况下,它完成了它的工作。

于 2016-03-19T18:39:22.747 回答
1

编写一个映射到 list1 和 list1 中每个元素的函数

  1. 在 list2 中找到它。如果它不在 list2 中,则它会失败。
  2. 否则它将它从 list2 中删除
于 2013-04-02T10:31:22.043 回答
1

将列表视为集合以及是否可以使用更多命令,例如:

INTERSECTION SET-DIFFERENCE EQ

你可以定义这个函数:

(defun equal-lists (list1 list2)
  (and (eq (null (intersection list1 list2)) nil)
       (null (set-difference list1 list2))))

那么如果交集不是空集,并且差是空的,那么set1等于set2。

于 2014-04-28T07:53:51.057 回答
1

如果两个列表是彼此的子集,则它们包含相同的元素。

(defun same-elements (l1 l2)
  (and (subsetp l1 l2) (subsetp l2 l1)))
于 2017-04-02T02:51:49.143 回答
0

如果您的元素是数字,或者您有一个不错的元素比较器(在这种情况下是按字母顺序排列),您可以简单地对两个列表使用“排序”过程,然后检查它们是否相同。

从理论上讲,整个操作的复杂度将在 O(N log(N)) 左右(因为 'sort' 的 Lisp 实现非常好)。至于 Hedi 的回答,复杂性将类似于 O (N² / 2) (因为“成员”将被调用 N 次,并且每次调用的平均时间为 (N / 2))。

于 2013-11-27T19:16:17.807 回答
0
(defun same ( a b )
`(cond
(( null a )'same )
((member(car a ) b ) (same(cdr a ) b ))
(t'nosame )))

(defun entre ( )
(let(( a ) ( b ))
(princ " list a : " ) (setq a (read ))
(princ " list b : " ) (setq b (read ))
(if (= (length a ) (length b )) (same  a b ) 'nosame )))
于 2016-07-22T04:22:48.020 回答