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
L'état est un tuple. Le premier élément est un drapeau booléen indiquant si nous avons déjà supprimé un élément de la liste. Le deuxième élément est une option: certains lorsque nous voulons émettre l'élément, aucun autrement.
La dernière ligne prend les deuxièmes éléments des états et pour chacun d'eux émet la valeur enveloppée (dans le cas de Some) ou ne fait rien (dans le cas de None).
Les clauses de garde peuvent être sympa, mais dans ce cas je pense qu'elles les rendent plus confuses. Je pense juste '| h :: t -> si prédicat h alors (List.rev acc) @ t else boucle (h :: acc) t' est plus clair. – mydogisbox
Un avantage de cette réponse est qu'elle arrête le traitement lorsque la première valeur correspondante est atteinte, ce qui économise beaucoup de travail. – TheQuickBrownFox
Dans la version récursive en queue, vous pouvez changer le cas '[]' pour retourner l'entrée 'list' au lieu d'inverser l'accumulateur, qui est de toute façon la liste inversée. – TheQuickBrownFox