我有一个列表,例如
let stdCourseList = [(10,[100;101;102]); (11,[101]); (14,[]); (12,[100;101])];;
这是一个包含学生 ID 和类(class) ID 列表的列表
我想实现一个能够计算学生正在修读的类(class)数量的函数。 比如我这样做
numbOfCourse(stdCourseList,10)
我会得到 3,因为 id 10 的学生选修了 3 门类(class)
到目前为止我有这个代码:
let rec numbOfCourse = function
|(([], id)) -> 0
|(((id2:int,(y:int)::ys)::xs),id) ->
if id=id2 then 1 //should a code to count the list of the course
else numbOfCourse(xs,id);;
但是当我运行它时,我收到了这个错误
let rec numbOfCourse = function
------------------------^^^^^^^^
stdin(1471,25): warning FS0025: Incomplete pattern matches on this
expression. For example, the value '([(_,[])],_)' may indicate a case not
covered by the pattern(s).
我真的不明白为什么会出现此错误以及该错误的含义。有人可以帮我解释一下吗?处理嵌套列表的最佳方法是什么?
这部分有错吗?
(((id2:int,(y:int)::ys)::xs),id)
谢谢。
最佳答案
错误消息表明您的模式并不详尽。示例 ([(_,[])],_)
表示您的函数不处理类(class)列表由单个元素组成以及类(class)列表中的单个元素具有空列表作为其第二个成员。
整个模式是一个元组。元组模式的第二部分将匹配任何值;这就是下划线的意思。元组的第一部分是包含单个元素的列表:
[(_,[])]
单个元素是一个元组:
(_,[])
该元组的第一部分将匹配任何值;第二部分匹配空列表。
如果你知道你永远不会得到这样的类(class)列表,你可以忽略这个警告,但我发现最好在编译器发现不完整的模式匹配时添加失败案例,因为这样编译器会通知我我未能涵盖的其他情况。例如,如果您将此行添加到函数中,您将收到另一个警告:
| ([(_,[])],_) -> failwith "unexpected pattern"
警告是
Incomplete pattern matches on this expression. For example, the value '([;],_)' may indicate a case not covered by the pattern(s).
总的来说,我发现尝试编写分解复杂结构(如列表元组列表)的复杂模式是危险的。最好一次处理一层:
let rec f = function
| [], _ -> //your base case here
| (studentId, courseList) :: tail, idParameter when studentId = idParameter -> //one recursive case here
| _ :: tail, id -> // another recursive case here
如果您需要分解类(class) ID 列表,可以使用单独的 match
表达式来执行此操作,作为替换此处的一个递归情况
的表达式的一部分。 “分而治之”将使你的代码更容易推理。
不过,如果由于您的类(class)要求而无法选择,那么将该结构分解为一个列表应该很容易。只需将每个列表视为具有两种可能的状态:空和非空。这将减少排列的数量。
最后,您可能想阅读有关辅助函数以及如何编写尾递归函数的信息,尽管您可能仍处于类(class)中不应该使用它们的阶段。一个重要的概念是“累加器”。
关于list - F# 嵌套列表问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29153243/