【问题标题】:Compare a list of numbers with a variable将数字列表与变量进行比较
【发布时间】:2015-11-04 00:33:39
【问题描述】:

下面的函数旨在将列表中的每个数字(第二个参数)与第一个参数进行比较,并且对于列表中大于第二个参数的每个 num,对其进行计数并返回列表中元素的总数大于“阈值”

我的代码没有运行,因为我试图了解 Dr. Racket 中的递归是如何工作的,但我似乎无法理解。我只是很沮丧,所以只知道下面的代码不应该接近工作;函数式编程不是我的菜,哈哈。

(define (comp-list threshold list-nums)
  (cond [(empty? list-nums) 0]
        [(cons?  list-nums) (let {[my-var 0]}
                              (map (if (> threshold (first list-nums)) 
                                       threshold 2) list-nums ))]))

【问题讨论】:

    标签: scheme racket


    【解决方案1】:

    以下不使用 foldl 的 lambda(并且是递归的) - 你能理解它是如何工作的吗?

    (define (comp-list threshold list-nums)
      (cond [(empty? list-nums) 0]
            [else
             (cond [(> (car list-nums) threshold) (+ 1 (comp-list threshold (cdr list-nums)))]
                   [else (comp-list threshold (cdr list-nums))])]))
    

    测试:

    > (comp-list 1 '(1 1 2 2 3 3))
    4
    > (comp-list 2 '(1 1 2 2 3 3))
    2
    > (comp-list 3 '(1 1 2 2 3 3))
    0
    

    【讨论】:

    • 为什么在第一个 condelse 部分中有一个新的 cond?带有 3 个测试表达式的 cond 会更具可读性。
    • 我只是为了分离出结束条件。
    【解决方案2】:

    map 将过程作为第一个参数并将其应用于给定列表中的每个元素。由于您正在计算列出列表的内容是错误的。

    foldl 将过程作为第一个参数,将起始值作为第二个和一个或多个列表。它应用具有元素和起始值(或中间值)的过程,并且过程决定下一个中间值。例如。你可以用它来计算一个列表:

    (define (my-length lst)
      (foldl (lambda (x acc) (+ acc 1))
             0
             lst))
    
    (my-length '(a b c)) ; ==> 3
    

    您可以轻松地将其更改为仅在 x 大于某个阈值时计数,只需评估为 acc 以在不增加值时保持不变。

    更新

    my-length的递归解法:

    (define (my-length lst)
      ;; auxiliary procedure since we need
      ;; an extra argument for counting
      (define (aux lst count)
        (if (null? lst)
            count
            (aux (cdr lst)
                 (+ count 1))))
      ;; call auxiliary procedure
      (aux lst 0))
    

    必须对foldl 的过程进行相同的更改,以仅在某些情况下计算。

    【讨论】:

    • 你能详细说明“lambda”在做什么以及“acc”是什么意思吗?
    • lambda 只是制作程序的秘密词.. ((lambda (x) (+ x 10)) 5) ; ==> 15acc 只是一个常用参数名称,表示它是一个累积值。您可以选择任何您想调用它们的名称,但是使用一些常用名称来表明它们的用途是使代码更易于阅读的好方法。例如。 lst 是一个参数的通用名称,它应该获取一些东西的列表。
    • 我还没学过 fold1 也几乎没有 lambda 关键字。无论如何我可以使用递归来检查每个列表项是否小于某个值?
    • @CompScientist 在上面的 lambda 函数中,无论x 是什么,新的结果总是(+ acc 1)。但您可以选择返回 acc(+ acc 1),具体取决于 x 小于或大于阈值。
    • @CompScientist 添加了递归版本。您仍然需要修复它才能使用阈值。
    【解决方案3】:
    (define (comp-list threshold list-nums)
      (cond 
        [(empty? list-nums)  ; there are 0 elements over the threshold in an empty list
         0]
        [(cons?  list-nums)  ; in a constructed list, we look at the the first number
         (cond
           [(< threshold (first list-nums)) 
            (+ 1                                        ; the first number is over
               (comp-list threshold (rest list-nums))]  ; add the rest 
           [else 
            (comp-list threshold (rest list-nums))])])) ; the first number is lower
    

    【讨论】:

    【解决方案4】:

    一个简单的功能开始

    #lang racket
    
    (define (comp-list threshold list-nums)
      (define (my-filter-function num)
        (<  num threshold))
      (length (filter my-filter-function list-nums)))
    

    define 替换为lambda

    #lang racket
    
    (define (comp-list threshold list-nums)
      (length (filter (lambda (num) (< num threshold))
                      list-nums)))
    

    Racket 对filter 的实现

    DrRacket 中突出显示过程的名称并右键单击并选择“跳转到其他文件中的定义”将允许查看源代码。 filter的源代码具有指导意义:

      (define (filter f list)
        (unless (and (procedure? f)
                     (procedure-arity-includes? f 1))
          (raise-argument-error 'filter "(any/c . -> . any/c)" f))
        (unless (list? list)
          (raise-argument-error 'filter "list?" list))
        ;; accumulating the result and reversing it is currently slightly
        ;; faster than a plain loop
        (let loop ([l list] [result null])
          (if (null? l)
            (reverse result)
            (loop (cdr l) (if (f (car l)) (cons (car l) result) result)))))
    

    【讨论】:

      猜你喜欢
      • 2022-01-15
      • 2011-01-06
      • 1970-01-01
      • 1970-01-01
      • 2021-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多