2010-07-08 13 views
9

Sanırım böyle bir kodum var:OCAML'deki List.Map ile bir terimi nasıl atlayabilirim?

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

Bunu yapmanın bir yolu var mı? Öyleyse nasıl?

Öğeyi, bazı ölçütlerle eşleşiyorsa ve bunu yapmazsa görmezden gelmek isterim. Böylece List.filter çözüm olarak görünmüyordu.

cevap

12

SML, tam olarak bunu yapan bir işlev haritasına sahiptir. Ne yazık ki bu fonksiyon OCaml'de mevcut değildir. Ancak kolayca böyle kendiniz tanımlayabilirsiniz:

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) 

Kullanımı:

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

[1;3;4] dönecektir.

Ya da ygrek işaretli olarak filter_map from extlib kullanabilirsiniz.

+6

List.filter_map extlib'de – ygrek

4

Alternatif aşağıdaki gibi liste daha sonra sonuçlandı listesinde harita uygulamak filtreleyebilirsiniz:

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> 

Kullanımı: mapPartial bir eşdeğerini temin

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

Hem Batteries ve Extlib: onların List uzatıldı modül, ('a -> 'b option) -> 'a list -> 'b list türünün filter_map işlevini, harita işlevinin de öğeleri seçmesine izin vererek döndürür.

5

Başka bir çözüm doğrudan kullanmak olacak bir foldl:

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

Ama benim tercih Michael E gibi filter_map olduğunu

1

bunları ya boş listeleri tutmak istiyorsanız da listeleri Singleton değerleri haritalayabilirsiniz eğer yapmazsan, sonuçlara uy.

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