每月练习次数(SML中多个列表的迭代)
我在SML中有两个列表,比如列表A每月练习次数(SML中多个列表的迭代),sml,Sml,我在SML中有两个列表,比如列表A[(A,b,c),(d,e,f)]和列表b[b,e]。我想计算B中每一项与A中每三元组的第二个元素相匹配的出现次数。输出应该是2。因为b和e每一个都在A中出现一次 到目前为止,这是我的代码,但当我在B中从一个元素移动到另一个元素时,我的计数器总是设置为0。我知道在Java中,这只是一个简单的双for循环 fun number_in_months (d : (int * int * int ) list, m : (int) list) = if nul
[(A,b,c),(d,e,f)]
和列表b[b,e]
。我想计算B中每一项与A中每三元组的第二个元素相匹配的出现次数。输出应该是2。因为b
和e
每一个都在A中出现一次
到目前为止,这是我的代码,但当我在B中从一个元素移动到另一个元素时,我的计数器总是设置为0。我知道在Java中,这只是一个简单的双for循环
fun number_in_months (d : (int * int * int ) list, m : (int) list) =
if null m then 0
else if null d then number_in_months(d, tl m)
else if (#2(hd d)) = (hd m) then 1 + number_in_months (tl d, m)
else number_in_months(tl d, m)
代码没有在递归调用之间累积值。可能还有其他逻辑错误 使用递归和函数累积值是一种常见的模式,您可以了解更多。它的本质是使用
head
和tail
解构列表,直到列表为空,并在每次调用时累积一些值。下面的sum
函数就是一个简单的例子。当在列表A
中找到b
或e
时,这可以适用于您的示例,以累积acc
fun sum(numbers: (int) list) =
let fun sumR(numbers: (int) list, acc: int) =
if null numbers
then acc
else
sumR(tl numbers, hd numbers + acc)
in
sumR(numbers, 0)
end
在[1,2,3]
上运行会给出:
val sum = fn : int list -> int
- sum([1,2,3]);
val it = 6 : int
注意,我有意含糊其辞,因为这是一个关于编程语言课程的Coursera作业的问题。正如您所提到的,在任何命令式编程语言中,这都是一个嵌套/双循环。您实际上缺少的是第二个循环 “内部”循环遍历
d
的所有元素,完成后,“外部”循环尝试弹出m
的顶部元素并从头开始,如代码的这一行所示:
else if null d then number_in_months(d, tl m)
但是,正如您所看到的,您刚刚测试了列表d
为空,并将此列表(完全相同的列表)提供给m
尾部的递归调用,然后每个后续调用都将属于相同的情况,直到m
也为空并且返回0为止
因此,您缺少的是“保留一份”原始输入列表m
。这可以通过多种方式完成,但内部(helper)函数是最常用的函数,它甚至“看起来”像一个嵌套循环
fun number_in_months (d, m) =
let
fun nim' ([], y::ys) = nim (d, ys) (* 1 *)
| nim' (_, []) = 0 (* 2 *)
| nim' ((_, x2, _) :: xs, yss as (y::ys)) = ... (* 3 *)
in
nim'(d, m)
end
使用模式匹配上述代码会变得更简单,更不容易出错。在案例1中,“内部”循环已通过d
中的所有元素,因此使用外部函数的d
进行递归调用,该调用在任何时候都不会更改。在案例2中,“外部”循环已经遍历了m
的所有元素,我们返回0(加法的中性元素)。在案例3中,我们进行实际工作。这里使用了模式匹配,这样我们就不需要强制执行参数的类型,也不需要提取三元组的第二个元素,我们已经在变量x2
中找到了它。所有需要做的就是进行计算并使用xs
和yss
进行递归调用
这样做时,内部(helper)函数使用原始输入列表的“副本”
d
,并逐步遍历其元素(可能会对其进行修改),但我们始终获得原始输入列表的引用,我们可以在需要时使用它。如果我在[(1,2,3)(2,2,3)(4,2,3)],[2,4]上运行代码,谢谢您的回答我得到了答案6,这是中间2的总和。因此,它的累加问题是它应该继续下去,并且在第一个列表的中间元素中检查4,如果发现4,则应该将6更新到7。对于<代码> NothByIn个月< /代码>输入<代码> [1(2,3),(2,2,3),(4,2,3)],[2,4]的答案。应该是3,因为每个日期都有2
,因为月份和2
在月份列表中
是的,你是对的,应该是3而不是6,这是我的错误。你真的不想使用模式匹配而不是测试null
的空列表。这样,您也不需要显式地获取列表的开头和结尾,因为您已经将它们模式匹配为例如(x::xs)和(y::ys)。感谢您的解释,您指出的错误非常重要,我终于得到了我想要的。