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
Der Zustand ist ein Tupel. Das erste Element ist ein boolesches Flag, das angibt, ob wir bereits ein Element aus der Liste entfernt haben. Das zweite Element ist eine Option: Einige, wenn wir den Artikel ausgeben möchten, sonst keine.
Die letzte Zeile nimmt die zweiten Elemente aus den Zuständen und für jede von ihnen emittiert den verpackten Wert (im Falle von einige) oder nichts (im Falle von keiner).
Guard-Klauseln können nett sein, aber in diesem Fall glaube ich, dass sie es verwirrender machen. Ich denke nur '| h :: t -> wenn Prädikat h dann (List.rev acc) @ t else Schleife (h :: acc) t 'ist klarer. – mydogisbox
Ein Vorteil dieser Antwort ist, dass sie die Verarbeitung stoppt, wenn der erste übereinstimmende Wert erreicht wird, so dass viel Arbeit eingespart werden kann. – TheQuickBrownFox
In der Tail-rekursive Version können Sie den '[]' - Fall ändern, um die Eingabe 'list' zurückzugeben, anstatt den Akkumulator umzukehren, was sowieso nur die umgekehrte Liste ist. – TheQuickBrownFox