2010-07-08 20 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)