F#: How do i split up a sequence into a sequence of sequences

后端 未结 8 1983
执念已碎
执念已碎 2021-01-02 06:12

Background:

I have a sequence of contiguous, time-stamped data. The data-sequence has gaps in it where the data is not contiguous. I want create a

8条回答
  •  一向
    一向 (楼主)
    2021-01-02 06:13

    A Haskell solution, because I don't know F# syntax well, but it should be easy enough to translate:

    type TimeStamp = Integer -- ticks
    type TimeSpan  = Integer -- difference between TimeStamps
    
    groupContiguousDataPoints :: TimeSpan -> [(TimeStamp, a)] -> [[(TimeStamp, a)]]
    

    There is a function groupBy :: (a -> a -> Bool) -> [a] -> [[a]] in the Prelude:

    The group function takes a list and returns a list of lists such that the concatenation of the result is equal to the argument. Moreover, each sublist in the result contains only equal elements. For example,

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

    It is a special case of groupBy, which allows the programmer to supply their own equality test.

    It isn't quite what we want, because it compares each element in the list with the first element of the current group, and we need to compare consecutive elements. If we had such a function groupBy1, we could write groupContiguousDataPoints easily:

    groupContiguousDataPoints maxTimeDiff list = groupBy1 (\(t1, _) (t2, _) -> t2 - t1 <= maxTimeDiff) list
    

    So let's write it!

    groupBy1 :: (a -> a -> Bool) -> [a] -> [[a]]
    groupBy1 _    []            = [[]]
    groupBy1 _    [x]           = [[x]]
    groupBy1 comp (x : xs@(y : _))
      | comp x y  = (x : firstGroup) : otherGroups
      | otherwise = [x] : groups
      where groups@(firstGroup : otherGroups) = groupBy1 comp xs
    

    UPDATE: it looks like F# doesn't let you pattern match on seq, so it isn't too easy to translate after all. However, this thread on HubFS shows a way to pattern match sequences by converting them to LazyList when needed.

    UPDATE2: Haskell lists are lazy and generated as needed, so they correspond to F#'s LazyList (not to seq, because the generated data is cached (and garbage collected, of course, if you no longer hold a reference to it)).

提交回复
热议问题