Как избавиться от дубликатов в списке, но сохранить порядок - PullRequest
6 голосов
/ 16 ноября 2011

Я использую Средний студент с лямбдой в DrRacket, мне было интересно, как можно удалить дубликаты в списке, сохраняя порядок. Например, (remove-dup (list 2 5 4 5 1 2)) даст (list 2 5 4 1). Пока у меня есть это:

(define (remove-duplicates lst)
  (cond
    [(empty? lst) empty]
    [(member? (first lst) (rest lst)) 
     (remove-duplicates (rest lst))]
    [else (cons (first lst) (remove-duplicates (rest lst)))]))

, но есть проблема, поскольку она не соблюдает порядок. Может ли кто-нибудь указать мне правильное направление? Спасибо за ваше время.

Ответы [ 8 ]

11 голосов
/ 16 ноября 2011

Если ваша цель состоит в том, чтобы функциональность работала, а не задавался домашним заданием, вам не нужно ничего делать, просто используйте remove-duplicates:

Welcome to Racket v5.2.
-> (remove-duplicates (list 2 5 4 5 1 2))
'(2 5 4 1)
4 голосов
/ 21 февраля 2012

Это решение:

(define (remove-duplicates lon)
  (foldr (lambda (x y) (cons x (filter (lambda (z) (not (= x z))) y))) empty lon))
0 голосов
/ 30 ноября 2012

Старый вопрос, но это реализация идеи JY.

(define (dup-rem lst)
  (cond
    [(empty? lst) empty]
    [else (cons (first lst) (dup-rem (filter (lambda (x) (not (equal? (first lst) x))) lst)))]))
0 голосов
/ 29 ноября 2011

хм, у меня недавно был экзамен по ракетке: /

'стандартный' remove-duplicates работает нормально, но я использовал довольно большой в drRacket, поэтому его нужно было загружать, используя (require racket/list)

вот альтернативный способ:)

используя мутацию (не совсем в духе рэкет, но .. это работает.)

    (define (set l)
        (define the-set '())
            (begin (for-each
                       (lambda (x)
                            (if (member x the-set)
                                #t
                            (set! the-set (cons x the-set))))
                       l)
                   (reverse the-set)))

надеюсь, это поможет ... ура!

0 голосов
/ 17 ноября 2011

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

Вам нужно отслеживать уникальные предметы, которые вы найдете, вы можете сделать это, используя вспомогательный список, например, аккумулятор, чтобы отслеживать те, которые вы нашли до сих пор.

Всякий раз, когда вы смотрите на другой предмет, проверьте, не находится ли он во вспомогательном списке. Если он не добавлен во вспомогательный список.

Вы получите обратный порядок того, что вы пытаетесь найти, так что вы можете просто (перевернуть ...) это, и вы получите ответ.

0 голосов
/ 16 ноября 2011

Что вам нужно сделать, это сравнить в обратном порядке все время.Вы можете использовать функцию reverse, которая возвращает список в обратном порядке.Таким образом, вы всегда удаляете второе + вхождение элемента, а не первое.Вот пример, однако он использует let и if, а не выражение cond.

http://www.cs.bgu.ac.il/~elhadad/scheme/duplicates.html

Удачи в выполнении домашней работы:)

0 голосов
/ 16 ноября 2011

Последовательный просмотр списка, вставка каждого элемента в хэш-таблицу или другой словарь. Если вы попытаетесь вставить элемент, который уже находится в хэш-таблице, не добавляйте его в исходящий список.

0 голосов
/ 16 ноября 2011

SRFI-1 имеет delete-duplicates, хотя это неэффективно. (Я не слишком знаком с Racket, но, конечно, у него есть SRFI-1 и источник ...)

http://srfi.schemers.org/srfi-1/srfi-1.html#delete-duplicates

...