繁体   English   中英

我一直在尝试在 Racket 和 ML 中实现这个 function

[英]I'm stuck trying to implement this function in Racket and ML

我有这个任务:

考虑一个列表,其中每个元素都是长度为 2 的嵌套列表。每个嵌套列表的第一个元素是 0 或 1。每个嵌套列表的第二个元素是一些 integer。下面是 Scheme 中的示例输入。

 '((0 1) (1 2) (1 3) (0 4) (0 3))

出于这个问题的目的,我们将每个嵌套列表的第一个元素称为键,将嵌套列表的第二个元素称为值 现在考虑一个 function, count_by_cat ,它将这样的列表作为输入并产生一个二元素列表,其中

  • 第一个元素是所有以 0 为键的嵌套列表的值之和,并且
  • 第二个元素是所有以 1 为键的嵌套列表的值之和

在中实现count_by_cat

  • (a) 球拍,以及
  • (b) 毫升。

创建辅助函数可能会有所帮助。 也不要忘记mapfilterfilter不是 ML 的内置功能)。

我是 Racket 和 ML 的新手。 我坚持使用 Racket 中的访问列表和内容。 ML 的一些帮助也很好。

那么建议您使用高阶函数,例如mapfilter

事实上,将我们的数据作为一个整体来操作是很容易的,而不是在精神上一次只关注一个元素。 有些人可能会争论哪种方法(即前一种方法)函数式编程范例的本质。

在球拍中,

(define (count_by_cat ls)

“返回一个二元列表”

    (list
      ;; .....
      ;; ..... ))

其中第一个元素是

      (sum-of

所有嵌套列表的值

        (map value

以 0 为键

           (filter (lambda (x) (= 0 (key x))) ls)))

第二个元素是所有嵌套列表的值之和

      (sum-of
        (map value

以 1 为键

           (filter (lambda (x) (= 1 (key x))) ls))) ))

所以我们需要定义访问嵌套列表的辅助函数,

(define (key n) (car n))

(define (value n) (cadr n))

以及 function 的sum-of ,用于汇总列表中的数值:

(require math/base)

(define (sum-of ls)
    (sum ls))

这很容易编写,也很容易维护。

性能更高的代码将通过输入一次完成所有操作,如另一个答案所示。 它将所有逻辑融合到一个循环体中。 编写和维护起来可能更脆弱。

关于mapfilter的提示有点转移注意力(而且关于它们不是 ML 语言的错误也是错误的); 帮助程序 function 非常有用,但它是您想要的折叠,它基本上使用列表的当前元素和累加器值调用 function,并使用它返回的值作为下一个元素的累加器,最终返回值整个折叠。

例如,在 ocaml 中,使用折叠对整数列表求和:

let sum = List.fold_left (+) 0 [ 1; 2; 3; 4; 5 ];;

(+)是中缀运算符+的 function 版本)。

或者您在 Racket 中的问题,使用for/fold comprehension ,并返回两个值而不是双元素列表,这在 Racket 和 Scheme 中更为惯用(在 ocaml 和大概标准 ML 中,您将返回一个双元素元组而不是列表,并获取元组列表)。

(define (count-by-cat lol)
  (for/fold ([zero-sum 0]
             [one-sum 0])
            ([elem (in-list lol)])
    (case (first elem)
      [(0) (values (+ zero-sum (second elem)) one-sum)]
      [(1) (values zero-sum (+ one-sum (second elem)))])))

您也可以使用foldl ,但for/fold通常更易于使用,尤其是在处理多个值或其他重要情况时。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM