如何使用 chez 方案获得给定列表中所有元素的总和 >10?

Posted

技术标签:

【中文标题】如何使用 chez 方案获得给定列表中所有元素的总和 >10?【英文标题】:How do I get the sum of all elements >10 in a given list using chez scheme? 【发布时间】:2014-06-16 07:39:31 【问题描述】:

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

【问题讨论】:

【参考方案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)

【讨论】:

【参考方案2】:

添加一个函数,通过过滤掉不大于 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))))

【讨论】:

【参考方案3】:

如果您想保留一个通用的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,并且您只将原始列表中您打算求和的部分传递给它。

【讨论】:

【参考方案4】:

我想你可能想稍微概括一下,所以我制作了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 list library中找到折叠:

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

【讨论】:

【参考方案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 只是一个判断为真或假的条件。

【讨论】:

以上是关于如何使用 chez 方案获得给定列表中所有元素的总和 >10?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 chez 方案中加载 slib 库?

如何在 Chez-Scheme 中读取一行输入?

给定一个数字列表,如何创建总和的所有组合并返回这些总和的列表

如何获得可以使用给定数字形成的所有可能的 n 位数字?

从列表中删除特定值之后的所有元素

chez 方案中的数学手册