Haskell group
在那里描述:http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-List.html#v:group
示例:
group "Mississippi" = ["M","i","ss","i","ss","i","pp","i"]
有简单的F#方式吗?
我可以实现类似的东西
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 []
但我认为这有点难看,是否有更好的变体?
答案 0 :(得分:7)
这是我提出的,我认为这是合理的:
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']]
如果您还希望能够接收和返回无限序列,那么您需要与GetEnumerator
手工合作,这会变得更加丑陋。
答案 1 :(得分:3)
这是一个懒惰的版本。
open System.Collections.Generic
let groupConsecutive (sq : seq<_>) =
let rec group (e : IEnumerator<_>) xs =
seq {
if e.MoveNext() then
if e.Current = List.head xs then
yield! group e (e.Current :: xs)
else
yield List.rev xs
yield! group e [e.Current]
else
yield List.rev xs
}
seq {
let e = sq.GetEnumerator()
if e.MoveNext() then
yield! group e [e.Current]
}
答案 2 :(得分:2)
作为替代方案,这里是span和groupBy的原始haskell源实现的相当字面翻译。条件是需要继续k
以确保尾递归。
let span p =
let rec loop k = function
| x :: xs' when p x ->
let f (ys, zs) = x :: ys, zs
loop (f >> k) xs'
| xs -> k ([], xs)
loop id
let groupBy eq =
let rec loop k = function
| [] -> k []
| x :: xs ->
let (ys, zs) = span (eq x) xs
let f zss = (x :: ys) :: zss
loop (f >> k) zs
loop id
//Special case of 'groupBy', group by equality.
let group xs = groupBy (=) xs
group <| List.ofSeq "Mississippi"
// val it : char list list =
// [['M']; ['i']; ['s'; 's']; ['i']; ['s'; 's']; ['i']; ['p'; 'p']; ['i']]
答案 3 :(得分:1)
可能与列表和模式匹配?
let group s =
let rec loop = function
| x::xs, [] -> loop (xs, [x]) // First element
| x::xs, s::ss when x = s -> loop (xs, s::s::ss) // Same
| x::xs, ss -> ss :: loop (xs, [x]) // Different
| [], ss -> [ss] // Terminate
loop (List.ofSeq s, [])
group "Mississippi"
这不会赢得任何效率奖,但它(合理地)清楚。
答案 4 :(得分:-1)