I think the answer from @scrwtp is probably the nicest way to do this if your input is small enough (and you can turn it into an F # list to use pattern matching). I will add another version that works when your input is a sequence and you do not want to turn it into a list.
Essentially, you want to do something similar to Seq.takeWhile , but it gives you one additional element at the end (one for which the predicate does not work).
To use a simpler example, the following returns all numbers from a sequence up to those divisible by 5:
let nums = [ 2 .. 10 ] nums |> Seq.map (fun m -> m % 5) |> Seq.takeWhile (fun n -> n <> 0)
So, in principle, you just need to look for one element forward - for this you can use Seq.pairwise , which gives you the current and next element in the sequence "
nums |> Seq.map (fun m -> m % 5) |> Seq.pairwise // Get sequence of pairs with the next value |> Seq.takeWhile (fun (p, n) -> p <> 0) // Look at the next value for test |> Seq.mapi (fun i (p, n) -> // For the first item, we return both if i = 0 then [p;n] else [n]) // for all other, we return the second |> Seq.concat
The only ugliness is that you need to smooth out the sequence again using mapi and concat .
This is not very nice, so it would be nice to define your own function of a higher order, for example, Seq.takeUntilAfter , which encapsulates the behavior you need (and hides all ugly things). Then your code could just use the function and look nice and readable (and you can experiment with other ways to implement this).
source share