2017-09-04 14 views

答えて

6

あなたは

let rec removeFirst predicate = function 
    | [] -> [] 
    | h :: t when predicate h -> t 
    | h :: t -> h :: removeFirst predicate t 

かここで末尾再帰1(あなたは、スタックオーバーフローを恐れている場合)

let removeFirst predicate list = 
    let rec loop acc = function 
     | [] -> List.rev acc 
     | h :: t when predicate h -> (List.rev acc) @ t 
     | h :: t -> loop (h :: acc) t 
    loop [] list 
+0

ガード句はうまくいくかもしれませんが、この場合はもっと紛らわしいと思います。私はちょうど '| h :: t - >述語hならば(List.rev acc)@ else else(h :: acc)t'がより明確であれば。 – mydogisbox

+0

この回答の利点は、最初に一致する値に達したときに処理が停止し、多くの作業を節約できることです。 – TheQuickBrownFox

+0

テール再帰的なバージョンでは、アキュムレータを逆転させるのではなく、 '[]'の大文字と小文字を変更して入力 'list'を返すことができます。 – TheQuickBrownFox

3
let result = 
    items 
    |>List.scan (fun (removed, _) item -> 
     if removed then true, Some(item) //If already removed, just propagate 
     elif predicate item then true, None //If not removed but predicate matches, don't propagate 
     else false, Some(item)) //If not removed and predicate doesn't match, propagate 
     (false, None) 
    |>List.choose snd 

状態はタプルです。最初の要素は、すでにリストから項目を削除したかどうかを示すブール値のフラグです。 2番目の要素はオプションです:項目を出そうとするときには、そうでなければNoneを選択します。

最後の行は状態から2番目の要素を取り、それぞれがラップされた値(Someの場合)を出すか、何もしません(Noneの場合)。

+0

これはテストで最も遅く実行されました。 – Soldalma

2

は私のテストで速かった短い代わり、ある一般的な再帰関数を使用することができますこれまでに提案された他のものよりも:

let removeFirst p xs = 
    match List.tryFindIndex p xs with 
    | Some i -> List.take i xs @ List.skip (i+1) xs 
    | None -> xs 
0

直感的な解決策を目指します。

let removeAt index list = 
    let left, right = List.splitAt index list 
    left @ (List.skip 1 right) 

let removeFirst predicate list = 
    match List.tryFindIndex predicate list with 
    | Some index -> removeAt index list 
    | None -> list 

パフォーマンス(長いリスト)の場合。

let removeFirst predicate list = 
    let rec finish acc rem = 
     match rem with 
     | [] -> acc 
     | x::xs -> finish (x::acc) xs 
    and find l p acc rem = 
     match rem with 
     | [] -> l 
     | x::xs -> 
      if p x then finish xs acc 
      else find l p (x::acc) xs 
    find list predicate [] list 
関連する問題