More specifically, how do I generate a new list of every Nth element from an existing infinite list?
E.g. if the list is [5, 3, 0, 1, 8, 0, 3, 4, 0, 93, 211, 0
This seems a slightly better use of unfold:
everyNth :: Int -> [a] -> [a]
everyNth n = unfoldr g
where
g [] = Nothing
g xs = let (ys, zs) = splitAt n xs in Just (head ys, zs)
Or even better, use Data.List.Spit:
everyNth n = (map head) . chunksOf n
A lot of answers here already use Data.List.unfoldr, but I wanted to bring up an interesting way of writing the somewhat annoying unfold that may be helpful in other contexts:
{-# LANGUAGE TupleSections #-}
import Data.List (unfoldr)
import Data.Maybe (listToMaybe)
every n = unfoldr f . drop (n - 1)
where f xs = (,drop n xs) <$> listToMaybe xs
When the list is null, listToMaybe
returns a Nothing
, and fmap
similarly will then be Nothing
. However, if a Just
is produced, then the proper tuple is constructed by turning the head of the list into a tuple of the head and the rest of the values to use in the next iteration.
My version using drop:
every n xs = case drop (n-1) xs of
(y:ys) -> y : every n ys
[] -> []
Edit: this also works for finite lists. For infinite lists only, Charles Stewart's solution is slightly shorter.
Alternate solution to get rid of mod
:
extractEvery n = map snd . filter ((== n) . fst) . zip (cycle [1..n])
I nuked my version of Haskell the other day, so untested, but the following seems a little simpler than the others (leverages pattern matching and drop to avoid zip and mod):
everynth :: Int -> [a] -> [a]
everynth n xs = y : everynth n ys
where y : ys = drop (n-1) xs
Starting at the first element:
everyf n [] = []
everyf n as = head as : everyf n (drop n as)
Starting at the nth element:
every n = everyf n . drop (n-1)