F # filters only the first entry from the list

I have a list and I want to delete an item that matches some criteria, but only delete one item.

let items = [1;2;3] let predicate x = x >= 2 let result = items |> List.fold ... // result = [1;3] 

How to get a returned list of methods using [1; 3]?

+5
source share
5 answers

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 tail recursive (if you are afraid)

 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 
+6
source
 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 

A state is a tuple. The first element is a logical flag indicating that we have already removed an element from the list. The second element is an option: Some, when we want to emit an element, None otherwise.

The last line takes two elements from the states and for each of them emits a wrapped value (in the case of Some) or does nothing (in the case of None).

+3
source

Here is a short alternative that in my testing was faster than the others offered so far:

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

Guidance for an intuitive solution.

 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 

For performance (long lists).

 let removeFirst predicate list = let rec finish acc rem = match rem with | [] -> acc | x::xs -> finish (x::acc) xs and find lp acc rem = match rem with | [] -> l | x::xs -> if px then finish xs acc else find lp (x::acc) xs find list predicate [] list 
0
source

You can try this:

 let rec removeFirstOccurrence item screened items = items |> function | h::tail -> if h = item then screened @ tail else tail |> removeFirstOccurrence item (screened @ [h]) | _ -> [] 

Using:

 let updated = products |> removeFirstOccurrence product [] 
0
source

Source: https://habr.com/ru/post/1271501/


All Articles