Как получить сумму всех элементов>10 в данном списке, используя схему Chez?
Если создать схему Chez ex, которая делает СУММ всех элементов из lista_de_elemente
(define lista_de_elemente (list 2 4 1 12 32 3 34 12))
(define suma
(lambda()
(apply + lista_de_elemente)))
Как мне сделать сумму только элементов больше 10?
5 ответов
Общая техника состоит в том, чтобы сначала сформировать список элементов, которые вы хотите обработать. У вас уже есть этот список. Затем вы хотите применить одно или несколько преобразований к списку ввода. В этом случае нам не нужно делать никаких преобразований. Затем вы фильтруете список, чтобы получить только те элементы, которые удовлетворяют определенному условию. Наконец, вы применяете операции, объединяющие элементы в отфильтрованном списке.
Этот общий способ обработки списков описан в SICP как
enumerate -> transform (map) -> filter -> accumulate
Теперь, в этом случае, нам не нужно ничего перечислять или отображать, потому что у нас уже есть наш входной список, как я упоминал ранее.
(define (filter predicate sequence) (cond
((null? sequence) '())
(else (cond
((predicate (car sequence)) (cons (car sequence) (filter predicate (cdr sequence))))
(else (filter predicate (cdr sequence)))))))
(define (accumulate op initial sequence) (cond
((null? sequence) initial)
(else (op (car sequence) (accumulate op initial (cdr sequence))))))
(define (sum-list list) (accumulate + 0 (filter (lambda(x) (cond ((> x 10) #t) (else #f)))list)))
(sum-list (list 1 2 3 45 12))
;Output: 57
predicate
это просто условие, которое оценивается как истинное или ложное.
Я думаю, что вы можете обобщить это немного, поэтому я сделал filter-sum
такой, что вы можете сделать это:
#!r7rs ; #!r6rs for r6rs
(import (scheme) ; replace scheme with rnrs for r6rs
(only (srfi :1) filter fold)) ; remove filter for r6rs
;; I renamed you list
(define *lista-de-elemente* '(2 4 8 10 12 14 16))
(define (suma)
(define (>10? x)
(> x 10))
(filter-sum >10? *lista-de-elemente*))
(suma) ; ==> 42
Вот несколько возможных версий filter-sum
, У нас есть прямой рекурсивный путь:
(define (filter-sum predicate lst)
(cond ((null? lst) 0)
((not (predicate (car lst))) (filter-sum predicate (cdr lst)))
(else (+ (car lst) (filter-sum predicate (cdr lst))))))
Но это не очень хорошо, так как порядок или цифры не важны. Мы можем сделать этот хвост рекурсивно с аккумулятором, здесь с именем let
вместо подмышечной процедуры:
(define (filter-sum predicate lst)
(let loop ((lst lst)(acc 0))
(if (null? lst)
acc
(loop (cdr lst)
(if (predicate (car lst))
(+ acc (car lst))
acc)))))
Теперь такие петли с хвостовой рекурсией и аккумулятором можно превратить в складку. Вы найдете склад в библиотеке списка SRFI-1:
(define (filter-sum predicate lst)
(fold (lambda (x acc)
(if (predicate x)
(+ acc x)
acc))
0
lst))
Большая часть кода теперь, если вы должны добавить или нет. С filter
Вы можете отфильтровать так, чтобы можно было добавить каждый элемент в сгибе:
(define (filter-sum predicate lst)
(fold + 0 (filter predicate lst)))
filter
также находится в списке библиотеки SRFI-1. Теперь, если вы знаете, что ваш список чисел выше 10 короткий. Как несколько сотен, вы можете полностью изменить fold
для apply
и это может даже стать немного быстрее, но вы делаете ограничения на длину списка. (Многие системы схем выдвигают аргументы в стеке ограниченного размера, в то время как сворачивание накапливает список по одному элементу за раз.)
Используя filter
:
(define suma
(lambda()
(apply + (filter (lambda (e) (> e 10)) lista_de_elemente))))
КСТАТИ, suma
должен иметь список в качестве аргумента:
(define suma
(lambda(lst)
(apply + (filter (lambda (e) (> e 10)) lst))))
(suma lista_de_elemente)
Если вы хотите сохранить обобщенный suma
вместо определения suma, который включает в себя фильтр, вы можете вместо этого определить suma, которая просто суммирует, а затем отфильтровать свой список при передаче его в качестве параметра:
(define elems (list 2 4 1 12 32 3 34 12))
(define (suma lst)
(apply + lst))
(suma (filter (lambda (x) (> x 10)) elems))
Теперь у вас есть ваш обобщенный sum
, и вы передаете ему только ту часть исходного списка, которую вы намереваетесь суммировать.
Добавьте функцию, которая возвращает список, отфильтровывая числа не больше 10. Передайте возвращаемое значение этого в apply
как у тебя.
(define (get-greater-than-ten lst)
(define (helper in out)
(if (null? in)
out
(if (> (car in) 10)
(helper (cdr in) (append out (list (car in))))
(helper (cdr in) out)))
(helper lst `()))
Используйте это как:
(define suma
(lambda()
(apply + (get-greater-than-ten lista_de_elemente))))