Попытка заменить все экземпляры элемента в списке новым элементом [Racket] - PullRequest
0 голосов
/ 16 марта 2019

Как сказано в заголовке, я пытаюсь написать функцию, которая принимает список, переменную и элемент, а затем заменяет все экземпляры переменной в списке этим элементом.

Например:

(замена '(C или (D или D))' D #f) вернет

'(C или (#f или #f)))

Прямо сейчас у меня есть:

(define (substitute lst rep new)
  (cond ((or (null? lst))
     lst)
    ((eq? (car lst) rep)
     (cons new (substitute (cdr lst) rep new)))
    (else
     (cons (car lst) (substitute (cdr lst) rep new)))))

, который не проверяет вложенные списки, как в моем примере, хотя он отлично работает, когда они не являются частьюinput.

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

Ответы [ 2 ]

0 голосов
/ 24 марта 2019

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

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

(define (subst l rep new)
  (cond ((null? l)
         '())
        ((list? (car l))  ; Check if it is a nested list.
         (cons (subst (car l) rep new)  ; Replace occurrences in the nested list.
               (subst (cdr l) rep new)))  ; Replace occurrences in the rest of the list.
        ((eq? (car l) rep)
         (cons new
               (subst (cdr l) rep new)))
        (else
          (cons (car l)
                (subst (cdr l) rep new)))))

Пример использования (заимствовано из ответа, данного пользователем633183):

(subst '(a b c a b c a b c) 'a 'z)
;; '(z b c z b c z b c)

(subst '(a b c (a b c (a b c))) 'a 'z)
;; '(z b c (z b c (z b c)))

(subst '() 'a 'z)
; '()
0 голосов
/ 16 марта 2019

Вот еще одно решение, использующее сопоставление с шаблоном через match -

(define (sub l rep new)
  (match l
    ((list (list a ...) b ...)    ; nested list
     (cons (sub a rep new)
           (sub b rep new)))
    ((list a b ...)               ; flat list
     (cons (if (eq? a rep) new a)
           (sub b rep new)))
    (_                            ; otherwise
     null)))

Это работает так -

(sub '(a b c a b c a b c) 'a 'z)
;; '(z b c z b c z b c)

(sub '(a b c (a b c (a b c))) 'a 'z)
;; '(z b c (z b c (z b c)))

(sub '() 'a 'z)
; '()
...