Схема: Удалить повторяющиеся номера из списка

Я написал этот код, чтобы создать список из en количества заданных аргументов

(define (create-list . e)
   e)

Но мне это нужно, чтобы удалить любые повторяющиеся номера из списка внутри самого блока.

Я пробовал и искал часами и не могу найти решение, не размещая десятки строк кода в других блоках.

Например, скажем, мой ввод

(create-list . 2 2 3 5 5 )

Мне нужно, чтобы созданный список был "(2 3 5), а не" (2 2 3 5 5)...

Порядок чисел не имеет значения.


person spacing    schedule 05.12.2011    source источник
comment
См. также stackoverflow.com/a/8651932/450148.   -  person Felipe    schedule 20.08.2014


Ответы (3)


В принципе, вам нужно сделать что-то вроде:

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

Я могу придумать очень простой, но, вероятно, неэффективный способ сделать это:

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

Если вы не можете использовать существующие функции, такие как filter, вы можете создать их самостоятельно:

(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)))))
person Tikhon Jelvis    schedule 05.12.2011
comment
можно ли создать такой же код только с помощью cdr/car/cons и примитивных процедур? (без фильтра/головы/хвоста) - person spacing; 05.12.2011
comment
Да. На самом деле, head и tail уже просто car и cdr соответственно (на мой взгляд, слишком много Haskell). - person Tikhon Jelvis; 05.12.2011
comment
Кроме того, обратите внимание, что мой синтаксис может немного отличаться - я использовал Haskell совсем недавно, и я когда-либо использовал только stk, который является устаревшим интерпретатором схем. - person Tikhon Jelvis; 05.12.2011
comment
Извините, я не привык к этому. Только что проверил отредактированный ответ. Благодарю вас! - person spacing; 05.12.2011
comment
Как правило, filter принимает список и предикат (функция, которая возвращает значение true или false) и возвращает список, содержащий только те элементы, для которых предикат возвращает значение true. Вы можете думать об этом как о select-where. - person Tikhon Jelvis; 05.12.2011
comment
@spacing: есть веская причина, по которой вы не привыкли к этому - использование head и tail не происходит из Scheme, они происходят из другого языка, который я использовал. - person Tikhon Jelvis; 05.12.2011

Этот быстрее:

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

Но еще лучше то, что mit-scheme обеспечивает удаление дубликатов, что делает именно то, что вы хотите.

person abo-abo    schedule 26.04.2012

Самый эффективный (однократный обход списка) способ сделать это — определить функцию, которая проходит по списку поэлементно. Функция сохраняет список элементов, которые уже находятся в списке дедупликации.

Преимущество этого решения по сравнению с @Tikhon Jelvis заключается в том, что элементы списка не должны быть упорядочены для дедупликации.

Дана функция elem, которая сообщает, является ли a элементом l:

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

Мы можем перемещаться по списку, сохраняя каждый элемент, который мы не видели раньше:

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

Примечание: для эффективности это возвращает элементы в обратном порядке.

person amindfv    schedule 06.12.2011
comment
Нужны ли в моей версии элементы в любом порядке? Насколько я знаю, это не так. - person Tikhon Jelvis; 06.12.2011
comment
@Tikhon Jelvis: Похоже на то; Однако я не могу заставить его возвращать правильные значения. Пример: (create-list 3 5 4 3 4 6) возвращает (3 3) - person amindfv; 06.12.2011
comment
Это было не из-за порядка, а из-за того, что я случайно пропустил not в предикате фильтра. Я исправил это сейчас. - person Tikhon Jelvis; 07.12.2011