Is this possible somehow? I want to use tryPick and then continue with the "rest" of the collection.
I can only think of ugly ways to do this:
let sequence = Seq.init 5 (fun (i) -> i)
let pickedMember =
sequence
|> Seq.tryPick (fun (i) ->
if i = 2 then
Some i
else
None
);;
let sequenceWithoutPickedMember = sequence |> Seq.filter (fun (i) -> not(i=pickedMember.Value));;
It is not clear from your example what you want do when Seq.tryPick
returns None
. I'll assume that the whole expression shall return 'None' and that the function signature chooser:('a -> 'b option) -> source:seq<'a> -> ('b * 'a list) option
is acceptable for your use case.
You'll get the option of a tuple back, containing the picked value and the rest as a list. It does not need to be a sequence because you need to consume the whole input sequence eagerly to return the result. The laziness gone, we can as well use a list.
let tryPickWithRest chooser source =
source
|> Seq.fold (fun (picked, rest) x ->
match picked, chooser x with
| None, Some newlyPicked -> Some newlyPicked, rest
| _ -> picked, x::rest ) (None, [])
|> function
| Some picked, rest -> Some(picked, List.rev rest)
| _ -> None
[0..4]
|> tryPickWithRest (fun i -> if i = 2 then Some "found 2" else None)
// val it : (string * int list) option = Some ("found 2", [0; 1; 3; 4])
let tryPickWithRest' chooser source =
Seq.foldBack (fun x (picked, rest) ->
match picked, chooser x with
| None, Some newlyPicked -> Some newlyPicked, rest
| _ -> picked, x::rest ) source (None, [])
[-4..0]
|> tryPickWithRest' (fun i -> if i >= 2 then Some "found 2" else None)
// val it : string option * int list = (null, [-4; -3; -2; -1; 0])