【问题标题】:Filtering without pattern matching没有模式匹配的过滤
【发布时间】:2021-11-06 22:39:12
【问题描述】:

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

【问题讨论】:

  • “whatType”是怎么做的?作为一个猜测,我认为,你应该调用 f over (rez @ (hd (l))) tl(l)... if whatType (hd (l)) = type then f (rez @ [hd (l) ]) tl(l)... 或类似的东西.. 除非您给出“whatType”的作用,否则我只能猜测...还请详细说明您的预期输出。
  • 我从上下文猜测whatType 决定了提供的制造商使用什么类型的产品。
  • 为什么不允许模式匹配?通过模式匹配,这将更清晰,更容易推理。
  • @NalinRanjan 它依赖于许多其他函数,所以我认为不需要全部编写它们。基本上它需要(name, (num1, num2, num2)) : string * (int * int * int) 并基于数字返回一个“类型”的参数作为string。使用示例:whatType ("Hyundai", (3,4,5)) = "Vehicle" 所以由于数字是(3,4,5),函数告诉我们我们的值是"Vehicle"。希望我的解释足够好
  • @ChrisDutton 是的,您对whatType 的解释是正确的。我不能使用模式匹配,因为我的任务限制了我使用它

标签: sml


【解决方案1】:

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

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

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

【讨论】:

  • @mutter123,此回复为您提供了大量信息.. 特别是如果您正在学习... 希望您可以按照此回复获得所需的信息...
猜你喜欢
  • 2013-06-22
  • 2019-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-27
  • 2013-06-16
  • 1970-01-01
相关资源
最近更新 更多