2011-12-05 17 views
5

que escribió el código para crear una lista de en número de argumentos dadosEsquema: Retire los números duplicados de la lista

(define (create-list . e) 
    e) 

Pero lo necesito para eliminar cualquier número de duplicados de la lista dentro de este bloque en sí.

He intentado y buscado durante horas y no puedo encontrar una solución sin colocar docenas de líneas de código en otros bloques.

Por ejemplo digamos que mi entrada es

(create-list . 2 2 3 5 5) 

Necesito la lista creada para ser '(2 3 5) y no' (2 2 3 5 5) ...

El orden de los números no importa.

+0

Véase también http://stackoverflow.com/a/8651932/450148 –

Respuesta

4

Básicamente, lo que necesita hacer algo como:

(define (create-list . e) (dedupe e)) 

puedo pensar en una manera muy simple, pero probablemente ineficaz para hacer esto:

(define (dedupe e) 
    (if (null? e) '() 
     (cons (car e) (dedupe (filter (lambda (x) (not (equal? x (car e)))) 
            (cdr e)))))) 

Si no puede utilizar las funciones existentes como filter, puede hacer uno usted mismo:

(define (my-filter pred ls) 
    (cond ((null? ls) '()) 
     ((pred (car ls)) (cons (car ls) (my-filter pred (cdr ls)))) 
     (else (my-filter pred (cdr ls))))) 
+0

sería posible crear el mismo código con CDR/coche/contras y sólo los procedimientos primitivos? (Sin filtro/cabeza/cola) – spacing

+0

Sí. De hecho, 'head' y' tail' ya son simplemente 'car' y' cdr' respectivamente (demasiado Haskell en mi mente). –

+0

Además, tenga en cuenta que mi sintaxis puede estar un poco desacostumbrada. Hace poco que uso Haskell y solo he usado stk, que es un intérprete de esquemas obsoleto. –

0

El más eficiente (trave Siguiendo la lista una vez), la forma de hacerlo es definir una función que pasa por la lista elemento por elemento. La función almacena una lista de los elementos que ya están en la lista eliminada.

Una ventaja de esta solución sobre @Tikhon Jelvis, es que los elementos de la lista no necesitan estar en orden, para ser deduplicados.

Dada una función elem, que dice que si a es un elemento de l:

(define (elem? a l) 
     (cond ((null? l) #f) 
      ((equal? a (car l)) #t) 
      (else (elem? a (cdr l))))) 

Podemos recorrer la lista, almacenando cada elemento que no hemos visto antes:

(define (de_dupe l_remaining already_contains) 
    (cond ((null? l_remaining) already_contains) 
     ((elem? (car l_remaining) already_contains) (de_dupe (cdr l_remaining) already_contains)) 
     (else (de_dupe (cdr l_remaining) (cons (car l_remaining) already_contains))))) 

Nota : para la eficiencia, esto devuelve los elementos en orden inverso

+1

¿Mi versión necesita los elementos en algún tipo de orden? Hasta donde yo sé, no es así. –

+0

@Tikhon Jelvis: Parecía así; Sin embargo, no puedo lograr que devuelva los valores correctos. Ejemplo: "(create-list 3 5 4 3 4 6)" returns "(3 3)" – amindfv

+0

Eso no fue por orden, fue porque accidentalmente omití un no en el predicado del filtro. Lo arreglé ahora. –

2

Este es más rápido:

(define (remove-duplicates l) 
    (cond ((null? l) 
     '()) 
     ((member (car l) (cdr l)) 
     (remove-duplicates (cdr l))) 
     (else 
     (cons (car l) (remove-duplicates (cdr l)))))) 

Pero aún mejor, mit-scheme proporciona eliminar-duplicados, que hace exactamente lo que usted quiere.

0
(define (delete x) 
(cond 
((null? x) x) 
((= (length x) 1) x) | ((null? (cdr x)) x) 
((= (car x) (cadr x)) (delete (cdr x))) 
(#t (cons (car x) (delete (cdr x)))) 
) 
) 
Cuestiones relacionadas