OCaml中的列表匹配

时间:2018-09-12 00:35:05

标签: list recursion ocaml

我有一个正在Ocaml中使用的功能。它包含一个接受两个字符串列表并返回一个字符串列表的函数。该功能的操作如下。它扫描第一个列表中的每个字符串,如果在第二个列表中找到相应的匹配项,则返回该匹配项。如果第二个列表有重复的匹配项,则该匹配项将返回两次。这是我编写的描述预期行为的测试用例:

let test () : bool =
  (in_both [] ["Pearl"; "Steven"]) = []
;; run_test "in_both empty name list 1" test

let test () : bool =
  (in_both ["Pearl"; "Steven"] []) = []
;; run_test "in_both empty name list 2" test

let test () : bool =
  (in_both ["Pearl"; "Amethyst"; "Henry"] ["Pearl"; "Steven"]) = ["Pearl"]
;; run_test "in_both one repeat in both lists" test

let test () : bool =
  (in_both ["Pearl"; "Amethyst"; "Gary"; "Blair"] ["Pearl"; "Amethyst"; "Blair"]) 
  = ["Pearl";"Amethyst";"Blair"]
;; run_test "in_both three different repeats in both lists" test

let test () : bool =
  (in_both ["Garnet"; "Amethyst"; "Pearl"] ["Pearl"; "Pearl"]) 
  = ["Pearl";"Pearl"]
;; run_test "in_both two repeat in second list" test

这是我的函数实现:

let rec in_both (names1: string list) (names2: string list) : string list =
  begin match (names1, names2) with
  |([],[])-> []
  |([],hd2::tl2)-> []
  |(hd1::tl1,[])-> []
  |(hd1::tl1,hd2::tl2)->if contains_str names2 hd1 = true then hd1::in_both tl1 
  tl2 else in_both tl1 names2
  end

我所有的测试都通过了,但最后一个测试除外,在该测试中,"Pearl"似乎没有打印两次。我在实施中可能做错了什么?作为参考,这是我在in_both中调用的contains_str函数的函数定义:

let rec contains_str (l: string list) (name: string) : bool =
  begin match l with
  |[]-> false
  |hd::tl-> hd = name || contains_str tl name
  end

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

一种查看方式是contains_str太弱了,无法执行您想要的操作。您想知道字符串出现的次数多少次,而不仅仅是字符串是否出现。您可能考虑使用一个函数,该函数返回字符串列表a中的字符串b的出现列表(如果没有出现,则为空)。

此外,还有另一种情况,您当前的代码似乎无法正确处理:

# in_both ["a"; "b"] ["b"; "a"];;
- : string list = ["a"]

在我看来,没有理由仅因为在其中找到了tl2而跳到第二个列表(hd1)的末尾。可能第二个列表的标题出现在第一个列表的后面。