我确信有一个简单的功能可以做到这一点,它应该:
> groupEvery [1,2,3,4,5,6] 2
[[1,2],[3,4],[5,6]]
我只是不知道手和hoogle没有帮助..
我确信有一个简单的功能可以做到这一点,它应该:
> groupEvery [1,2,3,4,5,6] 2
[[1,2],[3,4],[5,6]]
我只是不知道手和hoogle没有帮助..
我不知道任何内置函数,但它可以很容易地实现:
slice :: Int -> [a] -> [[a]]
slice _ [] = []
slice n xs = hs : slice n ts
where (hs, ts) = splitAt n xs
它反复将其输入拆分为第一个n
元素和其余元素。或者,使用unfoldr
from 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
的实例Functor
。Applicative
或者使用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)))
Data.List.Split包中还有chunksOf函数,它是 Haskell 平台的一部分,完全符合您的描述。
或者,如果你喜欢单行:
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) . ([],)