我不认为有任何简单的方法可以使用内置的F#函数来实现这一点。但是,如果定义了一个助手操作,则可以很好地解决此问题。
groupAdjacentBy
它基于计算分组键的函数将列表中的相邻元素分组在一起。这就像
List.groupBy
,但它将具有相同键的元素分组,只要这些元素彼此相邻。
val groupAdjacentBy : ('a -> 'b) -> 'a list -> 'a list list
F#列表的实现如下:
module List =
let groupAdjacentBy f list =
let rec loop k group acc list =
match list with
| [] when List.isEmpty group -> List.rev acc
| [] -> List.rev ((List.rev group)::acc)
| x::xs when f x = k -> loop k (x::group) acc xs
| x::xs when not (List.isEmpty group) -> loop (f x) [x] ((List.rev group)::acc) xs
| x::xs -> loop (f x) [x] [] xs
if List.isEmpty list then []
else loop (f (List.head list)) [List.head list] [] (List.tail list)
现在,您可以通过将具有相同值的相邻元素分组并将小于3的所有组替换为包含零的等长组来解决原始问题:
[ 0; +1; +1; +1; 0; +1; -1; -1; 0; -1; -1; -1; -1;
+1; +1; -1; +1; +1; +1; +1; +1; +1; +1; 0]
|> List.groupAdjacentBy id
|> List.map (fun group ->
if List.length group >= 3 then group
else List.map (fun _ -> 0) group)
|> List.concat