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

私はリストを持っています。重複した空の文字列リストを持たないリストを返す関数を作成したいと思います。例えば、上記のundefinedリストが返されます:重複する文字列と空の文字列を削除する

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

私はそれが重複することなく、私のために返すこの関数を書くが、どのように私は空の文字列をテストして条件を追加することができます。

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

List.filter (fun s -> s <> "")の結果はその後、空の文字列を削除するには

答えて

5

ジャストパイプありがとうございました。これは、単純な、組成の方法だ、ヨーヨーuはまた、またはセットに変換することによって静かに、あなたの関数が二次である

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

注意、あなたが最初のリストをソートすることによって、より良い複雑さを持つことができ、それを削除するには、あなたの機能をハック可能性があり、バック。 Batteriesにはこれを行う機能があります。

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 

最初の行は、文字列のセットのタイプを定義します。

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

あなたは既に見て文字列のセットを使用することができます。

次に、uniquifyは補助機能を呼び出して、見たことのない文字列をリストとセットの両方に追加するか、単に文字列を破棄します。 accは反復テールを再帰的にするために使用されます(したがって、長いリストのスタックオーバーフローを避ける)。

複雑さはN²の代わりにO(N.log N)にあるので、このスキームを使用する方が優れています。

+0

@Febrice Le Fessant私はあなたのコードを試してみましたが、8行目(iter s set tail)コンパイラが私にこのエラーを教えてくれました:エラー: "この式はStringSet型ですが、文字列はstring型ですが、 " – Quyen

+1

8行目に少し間違いがありました。iterの最初の引数は文字列ではなく文字列リストです。 私は[TryOCaml](http://try.ocamlpro.com/)で試してみましたが、今は問題なく動作します。 – cago

関連する問題