现在我有一个SML功能:
method([1,1,1,1,2,2,2,3,3,3]);
返回:
val it = [[2,2,2],[3,3,3]] : int list list
但我需要它返回:
val it = [[1,1,1,1],[2,2,2],[3,3,3]] : int list list
这是我目前的代码:
- fun method2(L: int list) =
= if tl(L) = [] then [hd(L)] else
= if hd(tl(L)) = hd(L) then hd(L)::method(tl(L)) else [hd(L)];
- fun method(L: int list) =
= if tl(L) = [] then [] else
= if hd(tl(L)) = hd(L) then method(tl(L)) else
= method2(tl(L))::method(tl(L));
正如你所看到的,它错过了第一个方法2调用。关于如何解决这个问题的任何想法?我完全被难倒了。
答案 0 :(得分:0)
您的问题在if hd(tl(L)) = hd(L) then method(tl(L)) else
。这就是说如果尾部的头部等于头部,则继续处理,但不要将其添加到结果列表中。这将跳过第一个连续的相等值的块。我建议将这些功能的职责分开一点。执行此操作的方法是让method2
剥离下一个连续的值块,并返回一对,其中第一个元素将删除连续的块,第二个元素将具有剩余的列表。例如,method2([1, 1, 1, 2, 2, 3, 3]) = ([1, 1, 1], [2, 2, 3, 3])
和method2([2, 2, 3, 3]) = ([2, 2], [3, 3])
。现在,您可以继续致电method2
,直到该对的第二部分为nil
。
答案 1 :(得分:0)
我不太确定你要对你的代码做什么。我建议创建一个尾递归辅助函数,它传递三个参数:
1) The list of lists you are trying to build up
2) The current list you are building up
3) The list you are processing
在您的示例中,计算中间某处的典型调用如下所示:
helper([[1,1,1,1]], [2,2],[2,3,3,3])
通过查看最后一个参数([2,3,3,3]
)的头部以及当前正在构建的列表的头部([2,2]
),递归将起作用,因为它们是相同 - 最后一个参数末尾的2被分流到正在建立的列表中:
helper([[1,1,1,1]], [2,2,2],[3,3,3])
在递归的下一步中,然后比较磁头并发现它们是不同的(2!= 3),因此辅助函数将中间列表放在列表列表的前面:
helper([[2,2,2], [1,1,1,1]], [3],[3,3])
中间列表被重新初始化为[3],因此它将开始增长
最终你达到了这样的目标:
帮手([[2,2,2],[1,1,1,1]],[3,3,3],[])
然后将[3,3,3]添加到列表列表中,并返回此列表的 reverse 。
一旦定义了这样的辅助函数,main方法就会检查一个空列表,如果不是空的话,则初始化对辅助函数的第一次调用。以下代码充实了这些想法 - 使用模式匹配样式而不是hd
和tl
(我不是明确使用这些函数的忠实粉丝 - 它使得代码太像Lisp一样) 。如果这是家庭作业,那么你应该彻底了解它是如何工作的,然后将其翻译成涉及hd
和tl
的代码,因为如果你使用尚未学习的东西,你的教授会认为它是抄袭的。没有成为你自己的工作:
fun helper (xs, ys, []) = rev (ys::xs)
| helper (xs, y::ys, z::zs) =
if y = z
then helper(xs, z :: y :: ys, zs)
else helper((y::ys)::xs,[z],zs);
fun method [] = []
| method (x::xs) = helper([],[x],xs);