Is there a built-in function to get all consecutive subsequences of size n of a list in Haskell?

For example, I need a function:

gather :: Int -> [a] -> [[a]]
gather n list = ???

where gather 3 "Hello!" == ["Hel","ell","llo","ol!"].

I have a working implementation:

gather :: Int-> [a] -> [[a]]
gather n list = 
    unfoldr 
        (\x -> 
            if fst x + n > length (snd x) then 
                Nothing 
            else 
                Just 
                    (take 
                        n 
                        (drop 
                            (fst x)
                            (snd x)), 
                    (fst x + 1, snd x))) 
        (0, list)

but I wonder if there is something already built into the language for this? I looked at Data.List but didn't see anything.

+5
source share
2 answers

You can use tails:

gather n l = filter ((== n) . length) $ map (take n) $ tails l

or using takeWhileinstead filter:

gather n l = takeWhile ((== n) . length) $ map (take n) $ tails l

EDIT: you can remove the filter step by discarding the last nelements of the list returned from tails, as suggested in the comments:

gather n = map (take n) . dropLast n . tails
  where dropLast n xs = zipWith const xs (drop n xs)
+14
source

Tail drop can be arranged automatically, thanks to the zipping properties,

import Data.List (tails)

g :: Int -> [a] -> [[a]]
g n = foldr (zipWith (:)) (repeat []) . take n . tails

transpose . take n . tails. :

Data.List > g 3 [1..10]
    [[1,2,3], [2,3,4], [3,4,5], [4,5,6], [5,6,7], [6,7,8], [ 7,8,9], [8,9,10]]
Prelude Data.List > . 3. $[1..10]
[[1,2,3], [2,3,4], [3,4,5], [4,5,6], [5,6,7], [6,7,8], [ 7,8,9], [8,9,10], [9,10], [10]]

+5

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


All Articles