4

我确信有一个简单的功能可以做到这一点,它应该:

> groupEvery [1,2,3,4,5,6] 2
[[1,2],[3,4],[5,6]]

我只是不知道手和hoogle没有帮助..

4

3 回答 3

10

我不知道任何内置函数,但它可以很容易地实现:

slice :: Int -> [a] -> [[a]]
slice _ [] = []
slice n xs = hs : slice n ts
  where (hs, ts) = splitAt n xs

它反复将其输入拆分为第一个n元素和其余元素。或者,使用unfoldrfrom Data.List

slice n = unfoldr (\xs -> if null xs then Nothing 
                                     else Just (splitAt n xs))

更新:只是为了好玩,我尝试使用标准函数制作尽可能短的版本。到目前为止我有

import Data.Functor ((<$))
import Data.List (unfoldr)
import Data.Maybe (listToMaybe)

slice :: Int -> [a] -> [[a]]
slice n = unfoldr (\xs -> splitAt n xs <$ listToMaybe xs)

使用<$fromMaybe的实例FunctorApplicative或者使用for稍短但更难理解(->) [a]

slice n = unfoldr (liftA2 (<$) (splitAt n) listToMaybe)
slice n = unfoldr ((<$) <$> splitAt n <*> listToMaybe)

我尝试的最难以理解的版本是

import Control.Monad.Trans
import Control.Monad.Trans.Maybe
slice n = unfoldr (runMaybeT ((MaybeT listToMaybe) >> (lift $ splitAt n)))
于 2013-07-03T19:16:24.073 回答
6

Data.List.Split包中还有chunksOf函数,它是 Haskell 平台的一部分,完全符合您的描述。

于 2013-07-04T08:55:55.940 回答
1

或者,如果你喜欢单行:

slice :: Int -> [a] -> [[a]]
slice n = takeWhile (not . null) . map fst . drop 1 . iterate (splitAt n . snd) . (\a -> ([],a))

甚至:

{-# LANGUAGE TupleSections #-}
slice :: Int -> [a] -> [[a]]
slice n = takeWhile (not . null) . map fst . drop 1 . iterate (splitAt n . snd) . ([],)
于 2013-07-04T03:28:16.003 回答