Splitting a list into list of lists based on predicate

前端 未结 5 2005
感动是毒
感动是毒 2021-01-21 03:28

(I am aware of this question, but it relates to sequences, which is not my problem here)

Given this input (for example):

let testlist = 
    [  
       \         


        
5条回答
  •  有刺的猬
    2021-01-21 04:09

    Just reverse the list once up front, and then build the structure in order easily:

    let Shunt p l =
        let mutable r = List.rev l
        let mutable result = []
        while not r.IsEmpty do
            let mutable thisBatch = []
            while not r.IsEmpty && not(p r.Head) do
                r <- r.Tail 
            while not r.IsEmpty && p r.Head do
                thisBatch <- r.Head :: thisBatch
                r <- r.Tail
            if not thisBatch.IsEmpty then
                result <- thisBatch :: result
        result        
    

    The outer while deals with each 'batch', and the first inner while skips over any that don't match the predicate, followed by another while that grabs all those that do and stores them in the current batch. If there was anything in this batch (the final one may be empty), prepend it to the final result.

    This is an example where I think locally imperative code is simply superior to a purely functional counterpart. The code above is so easy to write and to reason about.

提交回复
热议问题