2015-10-15 4 views
1

Я очень благодарен за помощь. Я пытаюсь построить процедуру, которая удаляет дублированные элементы в списке. Эта часть проста. Но тогда я также хочу удалить дублированные элементы (которые также могут быть списками), и если это список, дублирующиеся элементы в этом списке также должны быть удалены, например (make-set (список 1 2 3 2 (список 1 3 2 4) 3 4) (список 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)))))))))) 

ответ

1

На самом деле, если вы хотите построить функцию 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, то это либо номер, либо набор.
+0

Большое спасибо за вашу помощь. Я очень это ценю. – simpan

+0

Это удовольствие! – Renzo

1

Спецификация 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.

+0

Да, во многих фиксированных шрифтах '1' и' lst' выглядят одинаково (и, в отличие от многих языков, в Racket и Scheme '1st' есть допустимое имя идентификатора). –

+0

Спасибо за ответ, но он не работает так, как я тоже хочу. (список 1 2 3 2 (список 1 2 3 2 4 4) 2 (список 1 2 3 2 4 4))) дает мне (1 3 (1 2 3 2 4 4) 2 (1 2 3 2 4 4)), но я хочу, чтобы он дал мне (1 3 (1 2 3 4) 2) в этом конкретном случае. Поэтому, если список является элементом, я также хочу, чтобы он удалял каждый дублированный элемент в этом конкретном списке (и обратите внимание, если два списка с одинаковыми элементами отображаются дважды, с теми же элементами, один из списков должен быть удален). Извините, если я немного неясен, надеюсь, теперь вы поймете это лучше, иначе сообщите мне. – simpan

+0

@simpan У меня есть обновление решения. Предложение '(list? (Car lst))' теперь вызывает 'make-set'. – soegaard

Смежные вопросы