I want to split a string in several chunks based on a specific value.
For example the list [1; 2; 3; 0; 2; 4; 0; 5; 6; 0; 7]
[1; 2; 3; 0; 2; 4; 0; 5; 6; 0; 7]
[1; 2; 3; 0; 2; 4; 0; 5; 6; 0; 7]
and check element 0
should return [[1; 2; 3]; [2; 4]; [5; 6]; [7]]
[[1; 2; 3]; [2; 4]; [5; 6]; [7]]
I've found a method that splits a list if the next element is lower than the current one
[1; 2; 3; 0; 2; 4; 0; 5; 6; 0; 7]
[1; 2; 3; 0; 2; 4; 0; 5; 6; 0; 7]
would return [[1; 2; 3]; [0; 2; 4]; [0; 5; 6]; [0; 7]]
[[1; 2; 3]; [0; 2; 4]; [0; 5; 6]; [0; 7]]
This is the method for the order ascending split
let split2 lst =
let folder (a, b) (cur, acc) =
match a with
| _ when a < b -> a::cur, acc
| _ -> [a], cur::acc
let result = List.foldBack folder (List.pairwise lst) ([List.last lst], [])
(fst result)::(snd result)
printfn "%A" (split2 thelist)
And this is my modification:
let folder (a) (cur, acc) =
match a with
| _ when a <> 0 -> a::cur, acc
| _ -> [], cur::acc
let split lst =
let result = List.foldBack folder (lst) ([], [])
(fst result)::(snd result)
printfn "%A" (split thelist)
I no longer need the pairwise
as I only check element by element, but the current
and acumulator
defined as []
confuse me and I am not sure if the solution is correct, even though I get the desired output
Is there an easier solution for this?
I would do it like this
let list = [1; 2; 3; 0; 2; 4; 0; 0; 5; 6; 0; 7]
list
|> Seq.fold (fun state number ->
match number with
| 0 -> []::state
| x ->
match state with
| [] -> [] // never here, actually
| h::t -> [x::h]@t
)
[[]]
|> List.map List.rev
|> List.rev
|> List.filter (List.isEmpty >> not)
So, your state is a list of lists (which is what you ultimately want, anyway). You need to reverse the inner lists, then the outer one (if you care about order).
I added the filter at the end to deal with the result of consecutive 0's, which produce empty lists. You could handle that in the folder function, it will just make the code a bit more verbose than it already is.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.