#lisp #racket
#lisp #ракетка
Вопрос:
Я пытаюсь придумать процедуру, которая отфильтровывает любое значение, отличное от числа. Например:
'(1 2 (a) 3) => '(1 2 () 3)
или '(1 2 (a 10 11 (b 2 (c))) 3) => '(1 2 (10 11 (2 ())) 3)
Это то, что у меня есть до сих пор, но на самом деле это не работает, потому что оно заменяет не числа пустым списком вместо ничего:
(define (filter-numbers lst)
(if (null? lst)
'()
(if (list? lst)
(cons
(filter-numbers (car lst))
(filter-numbers (cdr lst)))
(if (number? lst)
lst
'())))
)
Процедура выводит следующее:
> (filter-numbers '(1 2 (a) 3))
'(1 2 (()) 3)
вместо: '(1 2 () 3)
Ответ №1:
Вам нужно проверить, является ли элемент в подсписке числом, прежде чем принимать решение о cons
его выводе или нет. Я думаю, будет проще, если мы немного реструктурируем код; также несколько советов: не используйте list?
, предпочитайте pair?
, так как это быстрее (в отличие list?
от того, что не нужно проходить весь список). И предпочитайте cond
вместо вложенности if
s, ваш код будет легче читать. Вот что я имею в виду:
(define (filter-numbers lst)
(cond ((null? lst) lst)
((not (pair? (car lst)))
; check the element while still in a list, if we wait
; until we reach an atom it's too late to filter it out
(if (number? (car lst))
; either add the element to the output or skip it
(cons (car lst) (filter-numbers (cdr lst)))
(filter-numbers (cdr lst))))
(else (cons
(filter-numbers (car lst))
(filter-numbers (cdr lst))))))
Это работает так, как ожидалось:
(filter-numbers '(1 2 (a) 3))
=> (1 2 () 3)
(filter-numbers '(1 2 (a 10 11 (b 2 (c))) 3))
=> '(1 2 (10 11 (2 ())) 3)
Комментарии:
1. Большое вам спасибо за вашу помощь! Это потрясающе 🙂