我有以下数据:
[0,+ 1,+ 1,+ 1、0,+ 1,-1,-1、0,-1,-1,-1,-1,+ 1,+ 1,+ 1,-1,+ 1,+ 1,+1,+1,+1,+1,+1,0]
这是我想要的输出:
[0,+ 1,+ 1,+ 1、0、0、0、0、0,-1,-1,-1,-1、0、0、0,+ 1,+ 1,+ 1,+ 1,+1,+1,+1,0]
在源列中,数据可以为+ 1,-1或0。
在输出中,具有3个或更多顺序出现的+1和-1s可以保留;那些没有的,必须转换为0。
Python / Pandas实现是这样的:
s = df[data].where(df[data].groupby(df[data].ne(df[data].shift()).cumsum()).transform('size').ge(3), 0)
如何在F#中实现呢?
我认为没有使用内置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