Search code examples
functional-programmingf#

Apply transformation to combine some items within a list


I would like to know how I can apply the following transformation in F#.

I find it's similar to the fold because I need the previous and current value to take my decision but fold output isn't a list but a computed state.

I know how to do this in an imperative way but I would like to know how to do it in a functional mindset.

Thanks

let a = [ "1"; "2"; "3"; "A"; "4"; "5"; "B" ]

// if value = "A" or "B", combine with previous value

let expectedResults = [ "1"; "2"; "3A"; "4"; "5B"; ]

Solution

  • It's probably easiest to do it from right to left, so that you don't have to reverse the list after folding it:

    let combineLettersWithPreviousValues ss =
        let folder x = function
            | [] -> [x]
            | h :: t -> if h = "A" || h = "B" then x + h :: t else x :: h :: t
        List.foldBack folder ss []
    

    It's still a fold though, just a right fold...

    > combineLettersWithPreviousValues [ "1"; "2"; "3"; "A"; "4"; "5"; "B" ];;
    val it: string list = ["1"; "2"; "3A"; "4"; "5B"]
    

    This technique is generalisable to any sequence of lists (not just list of strings) and requires only a single pass and no list concatenation (only list cons (::)).