sml - 没有模式匹配的过滤
问题描述
我有一个(string * (int * int * int)) list * string
作为参数并给出(string * (int * int * int)) list
结果的函数。所以我有一个包含(string * (int * int * int))
值的列表,我需要在string
不使用模式匹配的情况下对其进行过滤。过滤完成后,该函数会给出过滤后的列表和(string * (int * int * int))
值。例如它应该像这样工作:
- listCars ( [ ("Samsung", (1,2,3)), ("Hyundai", (3,4,5)), ("Mersedes", (6,1,5))], "Vehicle" );
> val it = [("Hyundai", (3,4,5)), ("Mersedes", (6,1,5))] : (string * (int * int * int)) list
函数本身:
fun listCars ( (lst, type)
: (string * (int * int * int)) list * string)
: (string * (int * int * int)) list =
let
fun f (rez : (string * (int * int * int)) list
, l : (string * (int * int * int)) list)
: (string * (int * int * int)) list =
if whatType (hd (l)) = type then rez @ [hd (l)]
else f (rez, tl (l))
in f ([], lst)
end
但是当我在这个函数上执行上面的例子时
listCars ( [ ("Samsung", (1,2,3)), ("Hyundai", (3,4,5)), ("Mersedes", (6,1,5))], "Vehicle" );
它只给了我
> val it = [("Hyundai", (3,4,5))] : (string * (int * int * int)) list
预期输出:
> val it = [("Hyundai", (3,4,5)), ("Mersedes", (6,1,5))] : (string * (int * int * int)) list
所以基本上它不是将所有相应的元素添加到新列表中,我认为我在这一行中做错了:if whatType (hd (l)) = type then rez @ [hd (l)]
当我试图将相应的元素添加到新列表中时。我的错误是什么?
解决方案
在处理递归时,建立基本案例至关重要。过滤一个空列表的结果显然应该是一个空列表。
fun listCars (lst, productType) =
if lst = [] then
[]
接下来,当列表中的第一个元素与所需的产品类型匹配时,我们的情况是什么?嗯,它是第一个元素,添加到过滤列表其余部分的结果的前面。
fun listCars (lst, productType) =
if lst = [] then
[]
else if whatType (hd lst) = productType then
hd lst :: listCars (tl lst, productType)
最后,我们需要处理不满足条件的第一个元素,只需对剩余元素运行过滤器即可。
fun listCars (lst, productType) =
if lst = [] then
[]
else if whatType (hd lst) = productType then
hd lst :: listCars (tl lst, productType)
else
listCars (tl lst, productType)
请注意,并非所有类型注释都是必需的。您的 SML 编译器或解释器环境将根据需要推断类型。不过,您可以使用类型注释来限制类型。
现在看起来您正在为尾递归编写此代码,因为您正在使用辅助函数。我们需要处理的条件是一样的。我们只需要一个以 . 开头的累加器[]
。
fun listCars (lst, productType) =
let
fun aux (result, lst, productType) =
if lst = [] then
result
else if whatType (hd lst) = productType then
listCars (result @ [hd lst], tl lst, productType)
else
listCars (result, tl lst, productType)
in
aux ([], lst, productType)
end
请注意,这是该函数与模式匹配的样子。
fun listCars ([], _) = []
| listCars (lst, productType) =
let
fun aux (result, [], _) = result
| aux (result, hd::tl, productType) =
if whatType hd = productType then
listCars (result @ [hd], tl, productType)
else
listCars (result, tl, productType)
in
aux ([], lst, productType)
end
模式匹配与否,递归的关键在于系统地思考。
推荐阅读
- java - 带有切片和范围的 Android 布局自定义圆形进度条
- angular - 带有参数的角度路由redirectTo
- typescript - Typescript 无法识别 d.ts 模块
- node.js - npm 错误!缺少脚本:开始
- asp.net-mvc - 在 ASP .NET Core 中动态添加控件
- c# - 在 WinForms C# 中绘制实心圆
- vba - 用标签替换斜体文本
- android - Androidcontacts2.db读取mimetypes列(不是数据表中的记录)
- javascript - 如何在打字稿中以通用方式扩展 3rd 方类?
- android - 在 Android 上使用 React-Native 使用 `file://` URI 从本地应用程序缓存中获取文件返回“意外的 url”