letsjak
letsjak

Reputation: 359

Going through a list in Haskell

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

Answers (4)

Philipp Murry
Philipp Murry

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

David Fletcher
David Fletcher

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

Zeta
Zeta

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

ase
ase

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

Related Questions