11 votes

Comment sauter un terme avec List.Map dans OCAML ?

Supposons que j'ai un code comme celui-ci :

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

Existe-t-il un moyen de le faire ? Si oui, comment ?

Je veux à la fois manipuler l'élément s'il correspond à certains critères et l'ignorer dans le cas contraire. Ainsi, List.filter ne semble pas être la solution.

14voto

sepp2k Points 157757

SML possède une fonction mapPartial qui fait exactement cela. Malheureusement, cette fonction n'existe pas en OCaml. Cependant, vous pouvez facilement la définir vous-même comme ceci :

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)

Uso:

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

retournera [1;3;4] .

Ou vous pouvez utiliser filter_map d'extlib comme l'a souligné Ygrek.

7voto

Michael Ekstrand Points 12849

Les deux sites Piles y Extlib fournir un équivalent de mapPartial : leur extension List module sprovide a filter_map fonction du type ('a -> 'b option) -> 'a list -> 'b list permettant à la fonction de carte de sélectionner également des éléments.

5voto

Benoît Fraikin Points 452

Une autre solution serait d'utiliser directement un foldl :

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

Mais ma préférence est filter_map comme Michael Ekstrand prévu

4voto

0xFF Points 2047

Vous pouvez également filtrer votre liste puis appliquer la carte à la liste obtenue, comme suit :

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>

Utilisation :

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

2voto

rapha Points 11

Vous pouvez également faire correspondre des valeurs à des listes singleton si vous souhaitez les conserver ou à des listes vides dans le cas contraire, puis concaténer les résultats.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X