2016-02-01 3 views
0

В настоящее время пытается написать функцию фильтра, которая принимает список процедур и список номеров, удаляет процедуры, которые не возвращают true для каждого элемента списка чисел.запись фильтр функция используя foldr?

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

Использование foldr или карту, если это необходимо (не рекурсивный)

(define (my-filter ps xs) 
    (foldr (λ (x y) 
      (cons (ps x) y)) '() xs)) 

Как удалить процедуру, если она имеет по крайней мере одного #F?

т.е. в настоящее время

> (my-filter even? '(1 2 3 4)) 
(#f #t #f #t) 
> (my-filter even? (2 4)) 
(#t #t) 

хотят

> (my-filter (list even?) '(1 2 3 4)) 
(list) 
> (my-filter (list even?) '(2 4)) 
(list even?) 
+0

думаю:> (мой фильтр (список даже?) '(1 2 3 4)), должен возвращать: (список), typo – Chase

+0

Имеет ли значение, что вместо 'foldl' используется' foldr'? – naomik

+0

Я думаю, что это нормально – Chase

ответ

1

Начните с какой-то желаемое за действительное. Скажем, у нас есть ноу знать, если все xs возвращение #t для любого заданного f

(define (my-filter fs xs) 
    (foldr (λ (f y) 
      (if (every? f xs) 
       (cons f y) 
       y)) 
     '() 
     fs)) 

Теперь давайте определим every?

(define (every? f xs) 
    (cond [(null? xs) #t] 
     [(f (car xs)) (every? f (cdr xs))] 
     [else #f])) 

Давайте проверим это для (list even?)

(my-filter (list even?) '(1 2 3 4)) ; ⇒ '() 
(my-filter (list even?) '(2 4))  ; ⇒ '(#<procedure:even?>) 

Давайте добавим еще один испытание в смеси

(define (gt3? x) (> x 3)) 

(my-filter (list even? gt3?) '(2 4)) ; ⇒ '(#<procedure:even?>) 
(my-filter (list even? gt3?) '(4 6)) ; ⇒ '(#<procedure:even?> #<procedure:gt3?>) 

Прохладный!


Если вы хотите увидеть имена «довольно» процедуры вместо этого #<procedure:...> вещей, вы можете отобразить object-name над результирующим массивом

(map object-name (my-filter (list even? gt3?) '(4 6))) ; ⇒ '(even? gt3?) 

Даже если foldl даст вам перевернутый выход, Я все еще думаю, что в этом случае было бы лучше использовать foldl. Только мои 2 цента.

+0

Я вижу, спасибо! Быстрый вопрос: как вернуть результат как: (list even?) Вместо (# ). Минусы или список не работают. – Chase

+0

'# ' Это просто строковое представление процедуры 'even?' – naomik

+0

ahh, спасибо огромное – Chase

2

Вы можете решить эту проблему с помощью ракеток встроенного andmap процедуры, которая проверяет, если условие истинно для всех элементов в списке - как это:

(define (my-filter ps xs) 
    (foldr (lambda (f acc) 
      (if (andmap f xs) ; if `f` is true for all elements in `xs` 
       (cons f acc) ; then add `f` to the accumulated output 
       acc))   ; otherwise leave the accumulator alone 
     '()     ; initially the accumulator is an empty list 
     ps))    ; iterate over the list of functions 

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

Преимущество foldr состоит в том, что он сохраняет тот же порядок, что и входной список, если это не является обязательным требованием, то foldl более эффективен, поскольку внутри он использует рекурсию хвоста. В любом случае, он работает так, как ожидалось:

(my-filter (list even?) '(1 2 3 4)) 
=> '() 

(my-filter (list even?) '(2 4)) 
=> '(#<procedure:even?>) 
+0

Спасибо! Но я сомневаюсь, что мне разрешено использовать andmap, как и почти всю работу. : D – Chase

+0

Это позор :(это более приятное решение, используя 'andmap'. Помните, что в тот день, когда возникает необходимость снова. –

+0

Óscar, спасибо за обмен' andmap'. Я не знал о его существовании. – naomik

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