2010-07-08 3 views
9

Предположим, у меня есть некоторый код, как это:Как я могу пропустить термин с List.Map в OCAML?

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

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

Оба Batteries и Extlib обеспечивает эквивалент mapPartial: их расширительный List module sprovide a filter_map функция типа ('a -> 'b option) -> 'a list -> 'b list, позволяющая функции карты также выбирать элементы.

5

Другим решением было бы использовать непосредственно foldl:

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

Но мое предпочтение filter_map как Майкл E

1

Можно также отобразить значения Синглтон списки, если вы хотите, чтобы держать их или пустые списки если вы этого не сделаете, а затем сравните результаты.

List.concat (List.map (fun e -> if (e <> 1) then [e + 1] else []) my_list) 
Смежные вопросы