【问题标题】:Turn a list with common items in to a list of ordered pairs将包含常见项目的列表转换为有序对列表
【发布时间】:2013-07-08 19:21:13
【问题描述】:

我对函数式编程完全陌生;这是 SML 的家庭作业。

我有一个整数列表,我正在尝试获取有序对的列表,其中该对的第二个条目是第一个条目出现在初始列表中的次数。

例如:

[2,3,3,5] => [(2,1),(3,2),(5,1)]

我不希望有人实现这一点,而是让我了解我正在寻找的 what 类型的高阶函数,和/或正确方向的指针。同样,对于函数式编程来说是全新的,对于 SML 语言来说更是新的。

我最初的想法是我想使用map,但我不知道如何跟踪或合并相似的项目。我只能成功地将每个项目变成一个有序对,第二个条目等于 1... 完全没用。

【问题讨论】:

    标签: functional-programming sml smlnj


    【解决方案1】:

    因此,为此您可能需要使用折叠,例如 foldl

    一般来说,在决定是使用map 还是折叠(这里我将折叠表示foldlfoldr)时,您可以使用以下经验法则:

    如果您想要的列表与您进入的列表中的元素数量完全相同,您可能需要map。否则,你会想要弃牌。

    推理如下:对于列表中的每个元素,map 在输出中生成一个转换后的元素。另一方面,折叠更通用,可以做任何你想做的事情。 (你确实可以使用折叠来实现map。这并不意味着你当然不需要让事情变得不必要地复杂)

    为了完整起见,让我简要解释一下折叠的工作原理。折叠遍历一个列表(从左侧开始foldl,从右侧开始foldr,因此得名),一次在累加器中建立一个结果。

    让我们看一个例子:

    foldl (fn (e, a) => e + a) 0 [5, 3, 7, 10]
    

    这里e 是我们当前正在使用的元素,a 是累加器变量(即当前结果)。我们以a = 0 开头,因为我们指定0 作为起始值。

    |  e | a  | new a
    -------------------------
    | 5  | 0  |  5 +  0 = 5
    | 3  | 5  |  3 +  5 = 8
    | 7  | 8  |  7 +  8 = 15
    | 10 | 15 | 10 + 15 = 25
    |    | 25 | 
    

    这为我们提供了25 的最终a,我们看到该函数汇总了列表中的元素。请注意,在任何迭代中,a 的值是迄今为止列表中元素的总和,以及我们如何在每一步都扩展此列表以包含更多元素。

    这是我推荐的解决此问题的方法。

    • 考虑a 的基值应该是多少。 (与获取[] 作为输入的结果相同。)
    • 然后考虑如何从较小的列表中获取结果,并将其扩展为包含另一个元素。

    【讨论】:

      【解决方案2】:

      除了使用折叠,这里还有一个提示:由于[(2,1),(3,2),(5,1)]是最终结果,折叠使用的累加函数的返回值可以是这种类型; (int * int) list。然后,您将问题简化为

      foldl (fn (elem, acc) => ...) [] xs
      

      f 应插入 elem 的位置,例如5,进入accum,例如[(2,1),(3,2)]f 可以被认为是一个插入函数,或者等效地,调用这样一个插入函数,只要它产生类似 [(2,1),(3,2),(5,1)] 的东西(即,查看已经找到的元素,如果找到则增加它,或者如果它使用 count 1 插入它没找到。

      【讨论】:

        猜你喜欢
        • 2021-12-23
        • 2015-12-31
        • 2017-05-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-23
        • 2019-05-10
        • 2019-07-26
        相关资源
        最近更新 更多