模式匹配列表中任意位置特定元素的最佳方式是什么?
What's the best way to pattern match a specific element at any position in a list?
假设我有一些列表
["a"; "b"; "d"]
["a"; "c"; "d"]
元素可以按任何顺序排列。列表将包含 "b"
或 "c"
之一,但绝不会包含两者。
如果 "b"
在列表中,我想 return 一个特定的值,或者如果 "c"
在列表中,我想要一个不同的值。
我是 OCaml 的新手,但据我所知这是不可能通过模式匹配实现的,还是我错过了什么?
执行此操作最惯用的方法是什么?
如果我没理解错的话,你会得到一个未知列表,你知道它包含 "b"
或 "c"
,但不是两者,你想确定是哪种情况。甚至可能找到第一次出现的位置?
这是一个有趣的问题。首先你当然可以手写循环:
let rec find_b_or_c i = function
| [] -> raise Not_found (* assumed not to happen ? *)
| (("b"|"c") as x) :: _ -> (i, x)
| _ :: xs -> find_b_or_c (i+1) xs
in
let (i, x) = find_b_or_c 0 my_list in
(* … do something with the index and/or the letter
(for instance test whether x = "b") … *)
那么问题是结合已有的功能能不能写得更简洁/优雅。如果您对索引不感兴趣,您可以简单地使用 List.find
或其变体 return 一个选项:
let x = List.find (fun x -> x = "b" || x = "c") my_list in (* … *)
您还可以测试 "b"
与 List.mem
的成员资格(或更普遍的 List.exists
);然而,使用这种方法,一旦列表包含 "c"
(有一个很长的列表,开头有 "c"
但没有 "b"
,搜索就不会被短路,你会浪费很多时间)。
但是,没有办法用the standard functions获取索引,因为其中none个return个索引。这是故意的,因为列表索引很慢(线性时间),你不应该这样做。如果你真的想要索引,你必须使用上面的手动递归,或者写一个更通用的函数 find_with_index
.
假设我有一些列表
["a"; "b"; "d"]
["a"; "c"; "d"]
元素可以按任何顺序排列。列表将包含 "b"
或 "c"
之一,但绝不会包含两者。
如果 "b"
在列表中,我想 return 一个特定的值,或者如果 "c"
在列表中,我想要一个不同的值。
我是 OCaml 的新手,但据我所知这是不可能通过模式匹配实现的,还是我错过了什么?
执行此操作最惯用的方法是什么?
如果我没理解错的话,你会得到一个未知列表,你知道它包含 "b"
或 "c"
,但不是两者,你想确定是哪种情况。甚至可能找到第一次出现的位置?
这是一个有趣的问题。首先你当然可以手写循环:
let rec find_b_or_c i = function
| [] -> raise Not_found (* assumed not to happen ? *)
| (("b"|"c") as x) :: _ -> (i, x)
| _ :: xs -> find_b_or_c (i+1) xs
in
let (i, x) = find_b_or_c 0 my_list in
(* … do something with the index and/or the letter
(for instance test whether x = "b") … *)
那么问题是结合已有的功能能不能写得更简洁/优雅。如果您对索引不感兴趣,您可以简单地使用 List.find
或其变体 return 一个选项:
let x = List.find (fun x -> x = "b" || x = "c") my_list in (* … *)
您还可以测试 "b"
与 List.mem
的成员资格(或更普遍的 List.exists
);然而,使用这种方法,一旦列表包含 "c"
(有一个很长的列表,开头有 "c"
但没有 "b"
,搜索就不会被短路,你会浪费很多时间)。
但是,没有办法用the standard functions获取索引,因为其中none个return个索引。这是故意的,因为列表索引很慢(线性时间),你不应该这样做。如果你真的想要索引,你必须使用上面的手动递归,或者写一个更通用的函数 find_with_index
.