Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looking for Haskell `group` alternative in F#

Tags:

f#

Haskell group descripted there: http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-List.html#v:group

example :

group "Mississippi" = ["M","i","ss","i","ss","i","pp","i"]

Is there simple F# way of doing it?

I can implement something alike

let rec sameCounter (data : list<float>) el same (ss : list<float * int>) = 
    if data.Length > (el + 1) then
        if data.[el] = data.[el + 1] then
                              sameCounter data (el + 1) <| same + 1  <| ss
        else if same > 0 then sameCounter data (el + 1) <| 0         <| (data.[el], same) :: ss
             else             sameCounter data (el + 1) <| 0         <| ss
    else ss
let group d = sameCounter d 0 0 []

but it's a bit ugly way I think, is there better variant?

like image 694
cnd Avatar asked Dec 12 '22 05:12

cnd


1 Answers

This is what I came up with, I think it's reasonable:

let groupConsecutive sq =
    (Array.ofSeq sq, [])
    ||> Array.foldBack (fun x -> function
        | [] -> [[x]]
        | xs :: xss ->
            if x = List.head xs then
                (x :: xs) :: xss
            else [x] :: xs :: xss)
// val groupConsecutive : s:seq<'a> -> 'a list list when 'a : equality

groupConsecutive "Mississippi"
// val it : char list list = [['M']; ['i']; ['s'; 's']; ['i']; ['s'; 's']; ['i']; ['p'; 'p']; ['i']]

If you also want to be able to take and return infinite sequences, you'll need to work by hand with GetEnumerator and it gets much uglier.

like image 59
Tarmil Avatar answered Dec 18 '22 22:12

Tarmil