2012-02-17 32 views
5
let undefined = ["string"; ""; "string"; "boolean";"";"innermost"] 

Bir liste var ve yinelenen ve boş dize listesi olmadan bir liste döndüren bir işlev yazmak istiyorum. Örneğin yukarıda undefined liste döndürür:Yinelenen dize ve boş bir dize kaldırma

["string"; "boolean"; "innermost"] 

ben olması yinelenen olmadan benim için dönmek bu işlevi yazmak ama nasıl boş bir dize test ile koşul ekleyebilirsiniz.

let rec uniquify = function 
| [] -> [] 
| x::xs -> x :: uniquify (List.filter ((<>) x) xs) 

List.filter (fun s -> s <> "") için sonuç sonradan boş dize kaldırmak için

cevap

5

Hemen boru Çok teşekkür ederim. Bu kadar basit, kompozisyon yolu, yo u da, ya bir dizi dönüştürerek sessizce fonksiyonu kuadratik olan

let rec uniquify = function 
| [] -> [] 
| x::xs -> 
    (if x = "" then [] else [x]) @ uniquify (List.filter ((<>) x) xs) 

Not öncelikle listeyi sıralayarak daha iyi karmaşıklığını olabilir bırakmak için işlevinizi kesmek olabilir ve geri. Batteries, sizin için bunu yapacak işlevlere sahiptir.

module StringSet = Set.Make(String) 
let uniquify list = 
    let rec iter acc set list = 
    match list with 
    | [] -> List.rev acc 
    | s :: tail -> 
     if StringSet.mem s set then 
      iter acc set tail 
     else 
      iter (s :: acc) (StringSet.add s set) tail 
    in 
    iter [] StringSet.empty list 

ilk satır dizi kümesini tipini tanımlamak:

let do_stuff list = 
    let open Batteries in 
    List.remove (List.sort_unique String.compare list) "" 
7

Zaten görülen dizeleri bir dizi kullanabilirsiniz. Daha sonra, tanımsız olarak, hem listeye hem de kümeye daha önce hiç görülmemiş bir dize eklemek ya da yalnızca dizeyi atmak için yardımcı işlev çağırır. acc, yineleme kuyruğunu tekrarlamak için kullanılır (ve böylece uzun listelerde yığın taşmaları önlenir). Bu şemayı kullanmak, karmaşıklık N² yerine O (N.log N) içinde olduğundan daha iyidir.

+0

@Febrice Le Fessant Kodunuzu denedim ve 8 numaralı satırda (iter s set kuyruğu) derleyici bana bu hatayı veriyor: Hata: "Bu ifadenin türü StringSet.elt = dizgidir ancak bir ifadenin türden bir ifadesi bekleniyordu" ." – Quyen

+1

Hat 8'de küçük bir hata vardı, iter'in ilk argümanı sadece bir dize değil, bir dize listesidir. Sadece [TryOCaml] üzerinde çalıştı (http://try.ocamlpro.com/) ve şimdi iyi çalışıyor. – cago