2016-12-04 2 views
2

Я пытаюсь реализовать функцию, которая рекурсивно удаляет все лишние пробелы из заданного потока. Любые последовательные пробелы должны быть удалены, что позволяет использовать одно максимальное пространство между словами. Я не могу понять, как правильно это реализовать.Racket Scheme - Удаление повторяющихся последовательных символов из потока

Я попытался преобразовать поток в список и манипулировать им таким образом, но я просто не могу понять, как построить новый поток и вернуть его, основываясь на моих тестах для каждого элемента. Я попытался использовать поток-карту, но это не похоже на работу для меня в этой ситуации (удаление элементов, строительство нового потока)

Вот мой текущий сломаны реализация REMOVE-экстра-пространств:

(define remove-extra-spaces 
    (lambda (str) 
    (cond (not (not-more-than-one-space str 0) (stream-append (stream-first str) (remove-extra-spaces (stream-rest str)))) 
      (else (remove-extra-spaces (stream-rest str))) 
     ))) 


    (define not-more-than-one-space 
    (lambda (str count) 
     (cond ((stream-empty? str) #T) 
      ((equal? (stream-first str) #\space) (not-more-than-one-space (stream-rest str) (+ count 1))) 
      ((> count 1) #F) 
      (else #T) 
      ) 
    )) 

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

ответ

1

Вы знаете, как использовать stream-cons? Вероятно, это самый простой способ реализовать это. Вот моя реализация (использует SRFI 41 потока библиотека вместо racket/stream, потому что я больше знаком с этим):

(require srfi/41) 
(define-stream (collapse-spaces strm) 
    (stream-let loop ((was-space #f) 
        (strm strm)) 
    (cond ((stream-null? strm) strm) 
      ((char=? (stream-car strm) #\space) 
      (if was-space 
       (loop #t (stream-cdr strm)) 
       (stream-cons #\space (loop #t (stream-cdr strm))))) 
      (else (stream-cons (stream-car strm) 
          (loop #f (stream-cdr strm))))))) 

Пример запуск:

> (stream->list (collapse-spaces (stream #\f #\o #\o #\space #\space #\b #\a #\r))) 
(#\f #\o #\o #\space #\b #\a #\r) 
+0

Спасибо. Я рассмотрю использование потоков-минусов. Я применил его в мою функцию remove-extra-spaces, однако при попытке преобразовать его в список я получаю сообщение об ошибке. Я заменил stream-append потоками-минусами. Ошибка: поток-первых: нарушение контракта ожидается: (? И/с потоком (не/с поток пустой)?) Дано: #

+0

Должен ли я проводить какую-то внутреннюю рекурсии, возможно, с letrec, для выполнения этой задачи? Я пытаюсь понять вашу реализацию, поэтому я тоже могу это сделать. –

+0

Попробуйте написать версию, которая работает в списке вместо потока. То есть ваша функция должна потреблять список и создавать список с развалом пробелов. Если вы можете написать это успешно, потоковая версия легко конвертировать. –

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