How to combine equal sequence elements (functional programming)?

后端 未结 4 1938
情书的邮戳
情书的邮戳 2021-01-20 15:42

I want to write a function that takes in a sequence <1,1,2,2,3> and returns the sequence with equal elements grouped like <<1,1>, <2,2>, <3>>.

I\'m u

4条回答
  •  不知归路
    2021-01-20 15:57

    In Haskell you have group and groupBy. They're made with a helper function called span. Standard ML unfortunately does not have as rich a standard library, so you'll have to create the function yourself. But you could use the same approach:

    1. Define a function span that splits a list in two where the first part is the longest prefix for which some predicate is true, and the second part is the remainder of the list.

      fun span p [] = ...
        | span p (x::xs) = ... if p x then ... else ...
      

      For example,

      - span (fn n => n <= 3) [2,3,4,1,5]
      > val it = ([2,3], [4,1,5])
      

      This is a little difficult because you must somehow add x to the result of calling span p xs recursively, even though it returns a pair of lists; so you cannot just write x :: span p xs; you have to unpack the pair that is returned and return (x :: ys, zs) or (ys, x :: zs) (and stop recursing once p x is false).

    2. Define a function groupBy that uses span. The function that groupBy uses should have two arguments unlike in span where p took one argument: The first one is the element with which to group, and the second is the subsequent elements.

      fun groupBy f [] = ...
        | groupBy f (x::xs) = ... use span, f, x and xs to create (ys, zs) ...
                              ... ys is the first group ...
                              ... groupBy f zs is the remaining groups ...
      

      Here it helps if the function f is curried, i.e. has type

      'a -> 'a -> bool
      

      since then it can be used like val (ys, zs) = span (f x) xs.

    Feel free to ask follow-up questions if you want to use this approach.

提交回复
热议问题