I have a list and I want to remove an element matching some criteria but remove only one element.
let items = [1;2;3]
let predicate x =
x >= 2
let result = items |> List.fold ...
// result = [1;3]
How to achieve method returning list with [1;3]?
You can use a generic recursive function
let rec removeFirst predicate = function
| [] -> []
| h :: t when predicate h -> t
| h :: t -> h :: removeFirst predicate t
or a tail recursive one (if you fear a stack overflow)
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
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
The state is a tuple. The first element is a Boolean flag indicating whether we already have removed some item from the list. The second element is an option: Some when we want to emit the item, None otherwise.
The last line takes the second elements from the states and for each of them emits the wrapped value (in case of Some) or does nothing (in case of None).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With