List LISP:如何测试两个列表是否具有相同的元素?

List LISP:如何测试两个列表是否具有相同的元素?,list,lisp,equality,List,Lisp,Equality,我想编写一个函数,将两个列表作为参数,并检查第一个列表中的每个元素是否都包含在第二个列表中(元素的顺序无关紧要)。函数还将检查两个列表是否具有相同的长度(两个列表不能有重复的元素),因为如果没有,则函数将返回nill/false 例如: (A B C D E F)和(B E A F D C)具有相同的元素 (nil)和(nil)具有相同的元素 (abcdef)和(abcdefg)没有相同的元素 问题是我只知道一些基本的命令,我只能使用这些命令。这些几乎是我所知道的所有命令: CAR, CDR,

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

例如: (A B C D E F)和(B E A F D C)具有相同的元素 (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))) 

我希望我对这个问题解释得足够好。

编写一个函数,该函数映射到列表1以及列表1中的每个元素

  • 在列表2中找到它。如果它不在列表2中,那么它将失败
  • 否则它将从列表2中删除它

  • 您可以定义一个函数,该函数在列表包含另一个时返回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"))) 
    

    如果您的元素是数字,或者如果您有一个合适的元素比较器(在本例中是字母顺序),您可以简单地对两个列表使用“排序”过程,然后检查它们是否相同


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

    将列表视为一个集合,如果您可以使用更多命令,如:

    INTERSECTION SET-DIFFERENCE EQ
    
    您可以定义此函数:

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

    然后,如果交叉点不是空集合,且差异为空,则set1等于set2。

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

    (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 c)
    (a b c)
    。但是,在大多数情况下,它完成了它的工作。

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

    (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 )))
    
    (defun same-elements (l1 l2)
      (and (subsetp l1 l2) (subsetp l2 l1)))
    

    谢谢你的回答。是否可以在一个函数中编写所有这些内容?我想知道你为什么写成员函数;它在LISP中还不存在?当然有办法,但我不认为它会很简单!是的,成员函数已经存在,但我忘记了。我已经一年多没有用LISP编程了。请用更多信息编辑。不鼓励只编写代码和“试试这个”答案,因为它们不包含可搜索的内容,也不解释为什么有人应该“试试这个”。