【问题标题】:SML - Find occurences in lists to form ordered pairsSML - 在列表中查找出现以形成有序对
【发布时间】:2013-06-26 16:43:40
【问题描述】:

我正在尝试在 SML 中编写一个函数,该函数接受一个整数列表并输出一个有序整数对列表。有序对第一个 int 是输入列表中出现的 int,有序对中的第二个 int 是它在输入列表中出现的次数。此外,返回的列表应根据有序对中的第一个 int 升序排列。

例如输入列表[1, 1, 1, 2, 3, 3, 5] 将输出为[(1,3), (2, 1), (3, 2), (5, 1)]

到目前为止,我有一个使用foldl的函数


更新自原始帖子以来的代码。

fun turnIntoPairs l = foldl (fn (e, a) => if List.exists (fn (x, _) => x = e) a then x + 1 else a @ [(e, 1)]) [] l;

我在更新列表时遇到了问题,在该列表中找到了已在列表中的有序对 - 我想将一个添加到已在列表中找到的有序对中的第二个 int。

任何帮助将不胜感激!

C:\Program Files (x86)\SMLNJ\\bin\.run\run.x86-win32.exe: Fatal error -- Uncaught exception Error with 0
raised at ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27

[autoloading done]
C:\Users\Localadmin\Desktop\CS 671\Program 3\commonFactors.sml:1.87 Error: unbound variable or constructor: x
C:\Users\Localadmin\Desktop\CS 671\Program 3\commonFactors.sml:1.44-1.110 Error: types of if branches do not agree [literal]
then branch: int
else branch: (''Z * int) list
in expression:
    if (List.exists (fn <pat> => <exp>)) a
    then <errorvar> + 1
    else a @ (e,1) :: nil
[Finished in 0.5s with exit code 1]

【问题讨论】:

  • 看看你的错误。它抱怨findx 不存在。 find 我认为您的意思是 List.find,尽管该类型签名与您尝试提供的参数不符。
  • 另外,同样的问题正在回答here
  • 我看到了那个帖子,我在写这个问题的时候那个帖子发了。我使用这些信息开始编写这个我现在遇到问题的函数。
  • 所以我摆脱了存在,因为这不是我想要做的。我试图查看列表中是否有一对 (e, _)。我在问题帖子中更新了我当前的功能。 if List.exists (fn (x, _) =&gt; x = e) a then .... 部分是否适合我想要完成的任务?

标签: list recursion functional-programming sml smlnj


【解决方案1】:

不太确定如何修复您当前的程序,但您可以通过将其分成两部分来解决此问题:将相等的元素分组,然后对列表进行排序。

(* Groups successive equal elements into a tuples (value, count) *)
fun group (l as (x :: _)) = 
    let val (firstGroup, rest) = List.partition (fn y => x = y) l
    in 
        (x, List.length firstGroup) :: (group rest)
    end
  | group [] = []

(* Now that we have our elements grouped, what's left is to order
   them as required. *)
fun turnIntoPairs xs =
    ListMergeSort.sort (fn ((x, _), (y, _)) => x >= y) (group xs)

【讨论】:

  • 感谢您提供替代解决方案。理想情况下,我想修复自己的代码,以便更好地了解 foldl 的工作原理,而不仅仅是复制别人的代码。不过很好的解决方案!
【解决方案2】:

让我们看看你传递给foldl的函数:

(fn (e, a) => if List.exists (fn (x, _) => x = e) a then x + 1 else a @ [(e, 1)])

第一个问题(类型检查器抱怨的)是您的if 表达式返回x + 1a @ [(e, 1)],这似乎有问题,因为前者是int 类型的值后者的类型为(int * int) list

让我们使用一些我不会定义的辅助函数重写你的代码,看看它是否变得更清晰:

(fn (e, a) => if List.exists (fn (x, _) => x = e) a then increment a e else a @ [(e, 1)])

其中increment 的类型为(int * int) list -&gt; int -&gt; (int * int) list

你能实现increment吗?

【讨论】:

  • 我认为我无法实现该方法,因为我在尝试调用 increment a x 时遇到关于 x 未知的错误?
  • 对不起,应该是e,而不是x。已更新。
【解决方案3】:

像 Gian 一样,我更愿意将其分为两个函数:一个是折叠的,另一个是插入的辅助函数。顺便说一句,插入函数将接受一个元素和一个现有的(int * int) list,就像折叠的累加器函数接受这两个参数一样。

通常我会写一个插入函数curried(即insert x xs),但如果我写的是非curried(即insert (x, xs)),我可以直接将它传递给foldl

fun insert (x, [])          = [(x,1)]
  | insert (x, ((y,c)::xs)) =
    if x = y then (y,c+1)::xs else (y,c)::insert (x, xs)

fun turnIntoPairs xs = foldl insert [] xs

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-27
    • 2015-10-08
    • 2019-08-03
    • 2015-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多