【问题标题】:OCaml pattern match arbitrarily many list elementsOCaml 模式匹配任意多个列表元素
【发布时间】:2017-01-17 20:31:53
【问题描述】:
假设我有[1;2;3;4;5;6;9] 和[1;2;3;9] 之类的列表,我想编写一个模式来捕获以1 开头并以9 结尾的列表,并捕获列表中间的值。这可能与 OCaml 的模式匹配有关吗?
我试过写类似的东西
match l with
| 1::middle::9
或
match l with
| 1::middle::9::[]
但我不确定这些是否符合我的要求,并且可能只匹配 3 个元素列表。有没有我可以采取的方法来匹配这样的事情?我应该使用嵌套模式匹配吗?
【问题讨论】:
标签:
list
pattern-matching
ocaml
【解决方案1】:
没有匹配列表末尾的模式,所以没有你想要的模式。你可以做两场比赛:
match l with
| 1 :: _ -> (
match List.rev l with
| 9 :: _ -> true
| _ -> false
)
| _ -> false
查找列表的结尾是线性时间操作。如果您的列表可能很长,您可能需要使用不同的数据结构。
【解决方案2】:
如果您只是检查列表的第一个和最后一个元素,您可能希望使用条件语句而不是模式匹配:
let is_valid l =
let open List in
let hd' = hd l in (* Get the first element of the list *)
let tl' = rev l |> hd in (* Get the last element of the list *)
if hd' = 1 && tl' = 9 then true else false
is_valid [1;2;3;4;5;6;9] (* bool = true *)
但是,如果您尝试提取中间模式,则可能值得使用模式匹配。由于他指出的原因(模式匹配无法匹配列表的末尾),我们可以做类似于 Jeffery 建议的事情:
let is_valid l =
let open List in
match l with
| 1 :: mid -> (* `mid` holds list without the `1` *)
(match rev mid with (* `rev_mid` holds list without the 9 but reversed *)
| 9 :: rev_mid -> Some (rev rev_mid) (* reverse to get correct order *)
| _ -> None)
| _ -> None
is_valid [1;2;3;4;5;6;9] (* int list option = Some [2; 3; 4; 5; 6] *)
然后用这个函数,你可以用它和简单的模式匹配来寻找有效列表的中间:
match is_valid l with
| Some middle -> middle (* the middle of the list *)
| None -> [] (* nothing — list was invalid *)