2

如果创建一个 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?

4

5 回答 5

3

我想你可能想把它概括一下,所以我做了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 列表库中找到 fold :

(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为 an apply,它甚至可能会变得更快,但是您正在限制列表的长度。(许多方案系统将参数推送到有限大小的堆栈上,而折叠将同时累积列表一个元素。)

于 2014-04-30T07:56:34.580 回答
1

一般技术是首先形成要处理的元素列表。你已经有了这份清单。然后,您想对输入列表应用一个或多个转换。在这种情况下,我们不需要进行任何转换。然后,您过滤列表以仅获取满足特定条件的元素。最后,您应用组合过滤列表中的元素的操作。

这种处理列表的一般方式在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只是一个评估为真或假的条件。

于 2014-04-30T17:43:47.257 回答
1

通过使用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)
于 2014-04-30T05:37:16.397 回答
0

添加一个函数,通过过滤掉不大于 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))))
于 2014-04-30T05:38:00.283 回答
0

如果您想保留一个 generalized 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))

现在您已经得到了 generalized sum,并且您只将原始列表中您打算求和的部分传递给它。

于 2014-04-30T05:45:32.207 回答