代码之家  ›  专栏  ›  技术社区  ›  Thomas

如何在F中的列表中只保留“稳定”值#

f#
  •  1
  • Thomas  · 技术社区  · 5 年前

    我有以下数据:

    这是我想要的输出:

    [0,+1,+1,+1,0,0,0,0,0,0,-1,-1,-1,-1,0,0,+1,+1,+1,+1,+1,+1,1,+1,0]

    在源列中,数据可以是+1、-1或0。

    在输出中,具有3个或更多连续出现的+1和-1可以保留;不具有连续出现的+1和-1必须转换为0。

    Python/Pandas实现如下:

    s = df[data].where(df[data].groupby(df[data].ne(df[data].shift()).cumsum()).transform('size').ge(3), 0)
    

    如何在F#中实现此功能?

    1 回复  |  直到 5 年前
        1
  •  2
  •   Tomas Petricek    5 年前

    我不认为有任何简单的方法可以使用内置的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