有没有办法将列表转换为Scheme中的集合?

时间:2011-08-21 12:41:21

标签: lisp scheme

我想测试列表中的相等性,但我真的只关心成员是相同的,而不是排序。有没有简单的操作员来检查这个?

一个相当简单的例子

(my-equal? (a b) (b a))

应该返回#t。

显然,这个特定的例子很容易通过检查两个列表然后反转第二个并再次检查来完成

(or (equal? (a b) (b a)) (equal? (a b) (reverse (b a)))

但总的来说有办法吗?我可以尝试编写一个函数,但我只能想象一些非常复杂的函数。我猜这必须是一个相当普遍的需求,我想知道Scheme是否有内置的运算符可以在这里完成工作。

我正在使用mit-scheme 9.0.1

3 个答案:

答案 0 :(得分:4)

如果您的实施有SRFI 1可用,则lset=可以实现您的目标:

Set operations on lists

答案 1 :(得分:3)

如果您使用的是Racket,我会指向this page,内置支持套装。

不,我知道,这不是回答你的问题。

答案 2 :(得分:1)

或者如果你想做旧学校,你可以写一些小函数。

我真诚地希望你不要用它来做作业。

(define (unordered-union-set set1 set2)
    (cond ((null? set2) set1)
        (else 
            (if (in-set? (car set2) set1)
                (unordered-union-set set1 (cdr set2)) 
                (cons (car set2) (unordered-union-set (cdr set2) set1))))))

(define (in-set? item set)
    (cond ((null? set) #f)
        ((equal? item (car set)) #t)
        (else (in-set? item (cdr set)))))

(define (set-equal? set1 set2)
    (if (equal? (length set1) (length set2))
        (if (equal? (length set1) (length (unordered-union-set set1 set2)))
            #t
            #f)
    #f))

使用set-equal?在任何两套。

这基于一些简单的集合论。如果两组等效基数的并集产生一个基数相当于第一组或最后一组基数的集合,则这些集合是等价的。

我写这篇文章的意思是说没有简单的操作符,但如果使用set union技巧则不需要很复杂的过程。

我的实现没有SRFI 1,但我非常怀疑lset =会比这个函数更快。

但是现在我读了你的评论,你需要它对'(1 1 2)和'(2 1)有效。由于这些不是集合,因此该方法不起作用,但不难实现。所以,实际上,这个过程相当于lset =。