删除列表中的重复元素

Delete duplicated elements in a list

我很感激您的帮助。我正在尝试构建一个删除列表中重复元素的过程。这部分很简单。但是后来我也想删除重复的元素(也可能是列表),如果它是一个列表,那么也应该删除该列表中的重复元素,例如(make-set(list 1 2 3 2(list 1 3 2 4 3 4) (list 1 3 2 4 3 4))) 应该是 '(1 3 2 (1 2 3 4)) 但在我们的例子中它变成了 '(1 3 2 2 3 4)。这不是我们想要的。我究竟做错了什么?谢谢:)

;; Checks if an element x appears in a list (set)
(define (element-of-set? x set)
  (cond (( null? set) false)
        ((equal? x (car set)) true)
        (else (element-of-set? x (cdr set)))))

;; Delete duplicated elements of a list (set)
(define make-set
  (lambda (lst)
    (cond ((null? lst) '())
          ((if (list? (car lst))
               (cond ((null? (car lst))
                      '()
                      )
                     ((element-of-set? (caar lst) (car lst)) (make-set (cdar lst))
                                                              )
                     (else (cons (caar lst) (make-set cadr lst))))
               (cond ((element-of-set? (car lst) (cdr lst)) (make-set (cdr lst)))
                     (else (cons (car lst) (make-set (cdr lst))))))))))

make-set 的规格有点不清楚,但也许这对你有用:

(define make-set
  (lambda (lst)
    (cond ((null? lst)                            '())
          ((list? (car lst))                      (cons (make-set (car lst)) (make-set (cdr lst))))
          ((element-of-set? (car lst) (cdr lst))                             (make-set (cdr lst)))
          (else                                   (cons (car lst)            (make-set (cdr lst)))))))

请注意 lst 不常用。

一个很好的约定是使用 x 作为列表中的元素并使用 xs 作为 x 元素列表。

实际上,如果您想构建一个函数 make-set 来管理广义的、无类型的集合概念(即可以包含数字或递归地包含其他集合的集合),则定义非常复杂。这是我的尝试。

;; check if x is contained in set
(define (contained? x set)
  (cond ((null? set) false)
        ((my-equal? x (car set)) true)
        (else (contained? x (cdr set)))))

;; check if all the elements of set1 are contained in set2
(define (set-contained? set1 set2)
  (cond ((null? set1) true)
        ((null? set2) false)
        (else (and (contained? (car set1) set2)
                   (set-contained? (cdr set1) set2)))))

;; check if set1 is equal to set2
(define (set-equal? set1 set2)
    (and (= (length set1) (length set2))
         (set-contained? set1 set2)))

;; check if x1 is equal to x2, when x1 and x2 can be sets or elements
(define (my-equal? x1 x2)
  (cond ((list? x1) (and (list? x2) (set-equal? x1 x2)))
        ((list? x2) false)
        (else (eq? x1 x2))))

;; add the element x to set, if not already present 
(define (add-to-set x set)
  (cond ((null? set) (list x))
        ((my-equal? x (car set)) set)
        (else (cons (car set) (add-to-set x (cdr set))))))

;; make a set from a list lst
(define (make-set lst)
  (cond ((null? lst) '())
        ((list? (car lst)) (add-to-set (make-set (car lst)) (make-set (cdr lst))))
        (else (add-to-set (car lst) (make-set (cdr lst))))))

(make-set (list 1 2 3 2 (list 1 3 2 4 3 4) (list 1 3 2 4 3 4)))  ; => '(1 3 (1 2 3 4) 2)

函数make-set通过依次将原始列表的每个元素插入新集合来构建集合,因此要检查元素是否已经存在(另外,如果元素是列表,首先它被转换成一个集合)。给定以下约定,其他功能应该很容易理解:

  1. 如果调用参数 set,该函数需要一个已表示为集合的列表。
  2. 如果一个参数被称为x,那么它要么是一个数字,要么是一个集合。