2013-04-02 277 views
3

我想编写一个函数,它需要两个参数列表并检查第一个元素中是否包含第二个元素(元素的顺序无关紧要)。该函数也将检查两个列表是否具有相同的长度(两个列表不能有重复的元素),因为如果不是,那么函数将返回nill/false。LISP:如何测试两个列表是否具有相同的元素?

例如: (ABCDEF)和(BEAFDC)具有相同的元件 (零)和(无)具有相同的元件

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

我希望我解释得很好的问题。

回答

6

当列表中包含另一个可以定义返回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"))) 
+1

感谢您的回答。是否有可能只用一个函数来编写所有这些?我想知道你为什么写成员函数;它在LISP中还不存在? – seby598

+0

当然有一种方法,但我认为这不会很简单!和是的成员函数已经存在,但我忘了。我没有在LISP上编程已经有一年多的时间了。 – Kira

2

收件它映射超过list1的和List1中

  1. 发现它在list2中的每个元件的功能。如果它不在list2中,则失败。
  2. 否则从列表2中删除
0

如果你的元素是数字,或者如果你有一个体面的比较元素(在这种情况下,这将是字母顺序),你可以简化对这两个列表使用'sort'过程,然后检查它们是否相同。

从理论上讲,对整个操作的复杂性将约为O(N日志(N))(因为Lisp实现“排序”是非常好的)。至于Hedi的回答,复杂性会像O(N²/ 2)那样(因为'成员'将被称为N次,每次呼叫的平均时间为(N/2))。

0

处理列表作为一组,如果你可以像使用多个命令:如果交集不是空集,以及性差异

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

然后:

INTERSECTION SET-DIFFERENCE EQ 

您可以定义此功能是空的,set1等于set2。

1

两个列表具有相同的元素时,在一个列表中的每个元素是其他列表中的一员,并且反之亦然。假设你可以使用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)中那样。但是,大多数情况下,它的工作是完成的。

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))) 
+0

请编辑更多信息。仅限代码和“尝试这个”的答案是不鼓励的,因为它们不包含可搜索的内容,也不解释为什么有人应该“尝试这个”。 – abarisone

0

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

(defun same-elements (l1 l2) 
    (and (subsetp l1 l2) (subsetp l2 l1))) 
相关问题