2010-07-08 46 views
9

假设我有一些像这样的代码:如何在OCAML中使用List.Map跳过一个术语?

List.map (fun e -> if (e <> 1) then e + 1 else (*add nothing to the list*)) 

有没有办法做到这一点?如果是这样,怎么样?

我想同时操作该项目,如果它符合一些标准,并忽略它,如果它不。因此List.filter似乎不是解决方案。

回答

12

SML有一个函数mapPartial,它正是这样做的。可悲的是,这个功能在OCaml中不存在。但是你可以自己简单地定义它是这样的:

let map_partial f xs = 
    let prepend_option x xs = match x with 
    | None -> xs 
    | Some x -> x :: xs in 
    List.rev (List.fold_left (fun acc x -> prepend_option (f x) acc) [] xs) 

用法:

map_partial (fun x -> if x <> 1 then Some (x+1) else None) [0;1;2;3] 

将返回[1;3;4]

或者您可以使用filter_map from extlib ygrek指出。

+6

list.filter_map in extlib – ygrek 2010-07-08 11:43:49

4

另外,您可以过滤列表,然后应用所得到的名单上图如下:

let map_bis predicate map_function lst = 
    List.map map_function (List.filter predicate lst);; 

# val map_bis : ('a -> bool) -> ('a -> 'b) -> 'a list -> 'b list = <fun> 

用法:

# map_bis (fun e -> e<>1) (fun e -> e+1) [0;1;2;3];; 
- : int list = [1; 3; 4] 
7

两个BatteriesExtlib提供的mapPartial等价物:其扩展List模块提供('a -> 'b option) -> 'a list -> 'b list类型的filter_map功能,允许地图功能也可以选择项目。

5

另一个解决方案是直接使用foldl

let f e l = if (e <> 1) 
      then (e + 1)::l 
      else l 
in List.fold_left f [] list 

但我的偏好是filter_map作为迈克尔·

1

,如果你想保持他们或空列表,您也可以映射值独居名单如果你不这样做,然后连接结果。

List.concat (List.map (fun e -> if (e <> 1) then [e + 1] else []) my_list)