Haskell, which can group a list of all n such that :: [a] & # 8594; Int & # 8594; [[a]]

I am sure that there is a simple function for this, it should:

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

I just don't know what to do, and hoogle didn't help.

+4
source share
3 answers

There is also a chunksOf function in Data.List.Split , which is part of the Haskell platform and does exactly what you described.

+6
source

I do not know any built-in function for this, but it can be easily implemented:

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

He repeatedly splits his input into the first n elements, and the rest. Or using unfoldr from Data.List :

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

Update: Just for fun, I tried to make the version as short as possible using standard features. While i have

 import Data.Functor ((<$)) import Data.List (unfoldr) import Data.Maybe (listToMaybe) slice :: Int -> [a] -> [[a]] slice n = unfoldr (\xs -> splitAt n xs <$ listToMaybe xs) 

using <$ from Maybe instance of Functor . Or a little shorter, but even less clear, using Applicative for (->) [a] :

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

The most obscure version of my attempts was

 import Control.Monad.Trans import Control.Monad.Trans.Maybe slice n = unfoldr (runMaybeT ((MaybeT listToMaybe) >> (lift $ splitAt n))) 
+9
source

Or if you like single-line:

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

Or even:

 {-# LANGUAGE TupleSections #-} slice :: Int -> [a] -> [[a]] slice n = takeWhile (not . null) . map fst . drop 1 . iterate (splitAt n . snd) . ([],) 
+1
source

Source: https://habr.com/ru/post/1489571/


All Articles