首页 > 解决方案 > 没有模式匹配的过滤

问题描述

我有一个(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)]当我试图将相应的元素添加到新列表中时。我的错误是什么?

标签: sml

解决方案


在处理递归时,建立基本案例至关重要。过滤一个空列表的结果显然应该是一个空列表。

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

模式匹配与否,递归的关键在于系统地思考。


推荐阅读