Reputation: 359
How do I go trough a list in Haskell when the list looks like:
[1,2,3,4,5,6,7,8,9,10,11,12]
and I want to take the first 3 elements:
[1,2,3]
and then go to the next 3 elements:
[2,3,4]
and so on...
Upvotes: 0
Views: 348
Reputation: 1682
Define your function like this slideThree (x:y:z:xs) =
and in your recursive call, call it like this slideThree (y:z:xs)
Make sure to add the proper checks if the list contains at least three elements.
Upvotes: 3
Reputation: 2818
Other answers are good - I just want to add that there's a succinct list comprehension:
[[x,y,z] | x:y:z:_ <- tails xs]
Obviously this wouldn't work so well if you wanted 1000-element sublists rather than 3.
Also, you should probably ignore this but I can't resist throwing in a fun point-free answer:
zipWith (const (take 3)) <$> drop 2 <*> tails
Upvotes: 1
Reputation: 105876
You could use zipWith3
:
zipWith3 (\a b c -> [a,b,c]) xs (drop 1 xs) (drop 2 xs)
But why stop there when one can generalize?
subLists :: Int -> [a] -> [[a]]
subLists n xs =
let ts = take n xs
in if length ts == n
then ts : subLists n (tail xs)
else []
This solution could be improved by takeN :: Int -> [a] -> Maybe [a]
, so that one doesn't need to check the length of ts
, but that's left as an exercise ;).
Upvotes: 3
Reputation: 13461
To create a sliding list of elements we can use tails
from Data.List
slide :: Int -> [a] -> [[a]]
slide n xs =
(filter (\xs -> length xs == n) . -- filter out all of length n
map (take n) . -- take only the first n elements of every tail
tails) xs -- find all tails
Using it:
λ> slide 3 [1..12]
[[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,11],[10,11,12]]
λ> map (\(x:y:z:[]) -> x + y + z) it
[6,9,12,15,18,21,24,27,30,33]
Upvotes: 3