5

与えられた

xs = [1,2,3,4,6,7,9,10,11]

復帰を目指しています

[[1,2,3,4],[6,7],[9,10,11]]

私はできると思った:

groupBy (\x y -> succ x == y) xs

しかし、これは次を返します:

[[1,2],[3,4],[6,7],[9,10],[11]]

少し検索すると、Haskell Data.List 提案ページから次の結果が返されました。

groupBy                 :: (a -> a -> Bool) -> [a] -> [[a]]
 groupBy rel []          =  []
 groupBy rel (x:xs)      =  (x:ys) : groupBy rel zs
   where (ys,zs) = groupByAux x xs
         groupByAux x0 (x:xs) | rel x0 x = (x:ys, zs)
           where (ys,zs) = groupByAux x xs
         groupByAux y xs = ([], xs)

彼らが与える例の1つは、まさに私が探しているものです:

groupBy (\a b -> a+1 == b) [1,2,3,4,6]
[[1,2,3,4],[6]]

groupByだから私の質問...少し劇的に見えるので、再定義するのではなく、これに対する別のアプローチはありますか?

編集...

以下のように実装することにしました。

pattern :: (Enum a, Eq a) => (a -> a) -> [a] -> [[a]]
pattern f = foldr g []
  where g a [] = [[a]]
        g a xs | f a == head (head xs) = (a : head xs): tail xs
               | otherwise = [a]:xs

これにより、次のことが可能になります。

*Main Map> pattern succ "thisabcdeisxyz"
["t","hi","s","abcde","i","s","xyz"]
*Main Map> pattern (+ 3) [3,6,9,12,1,2,3,2,5,8,23,24,25]
[[3,6,9,12],[1],[2],[3],[2,5,8],[23],[24],[25]]

またはまったく同じように機能するgroup-何らかの理由があるわけではありません:

*Main Map> let xs = [1,1,1,2,3,4,5,6,6,6,5]
*Main Map> group xs == pattern id xs
True
4

2 に答える 2

5

それを行うには多くの方法があります。1つの方法は、foldrを使用することです

f = foldr g []
  where g a [] = [[a]]
        g a xs@(x:xs') | a+1 == head x = (a : x): xs'
                       | otherwise = [a]:xs

これを実際に試してみます

*Main> f [1,2,3,4,6,7,9,10,11]
[[1,2,3,4],[6,7],[9,10,11]]
于 2013-01-09T13:13:43.097 に答える
3

xs厳密に増加している場合は

 myGrouping = map (map snd) . groupBy (\(u, v) (x, y) -> u - v == x - y) . zip [0..]

あなたの問題を解決します。

Prelude> myGrouping [1,2,3,4,6,7,9,10,11]
[[1,2,3,4],[6,7],[9,10,11]]
于 2013-01-09T13:49:19.607 に答える