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
The compiler or interpreter will compute the step size (subtract 1 since it's zero based):
f l n = [l !! i | i <- [n-1,n-1+n..]]
The Haskell 98 Report: Arithmetic Sequences
(This was in response to a comment asking for a solution without drop)
I couldn't see this solution, so:
every _ [] = []
every n (x:xs) = every' n (n-1) (x:xs)
where every' n c [] = []
every' n 0 (x:xs) = x : every' n (n-1) xs
every' n c (x:xs) = every' n (c-1) xs
works for finite and infinite list:
take 15 (every 3 [1..])
-- [3,6,9,12,15,18,21,24,27,30,33,36,39,42,45]
It's more elegant to solve a related problem first: Keep every element whose index is divisible by n.
everyNth n [] = []
everyNth n (x:xs) = x : (everyNth n . drop (n-1)) xs
And then to solve the example, use
everyNthFirst n = everyNth n . drop (n-1)
everyNthFirst 3 [5, 3, 0, 1, 8, 0, 3, 4, 0, 93, 211, 0 ...]
gives [0, 0, 0, ...]
Data.List.HT
from utility-ht
has sieve :: Int -> [a] -> [a]
.
See documentation and source:
{-| keep every k-th value from the list -}
sieve, sieve', sieve'', sieve''' :: Int -> [a] -> [a]
sieve k =
unfoldr (\xs -> toMaybe (not (null xs)) (head xs, drop k xs))
sieve' k = map head . sliceVertical k
sieve'' k x = map (x!!) [0,k..(length x-1)]
sieve''' k = map head . takeWhile (not . null) . iterate (drop k)
propSieve :: Eq a => Int -> [a] -> Bool
propSieve n x =
sieve n x == sieve' n x &&
sieve n x == sieve'' n x
An uglier, and more limited version of the accepted answer
every :: Eq a => Int -> [a] -> [a]
every n xs = if rest == []
then []
else head rest : every n (tail rest)
where rest = drop (n-1) xs
For "line golfing" it can be written like this:
every n xs = if rest == [] then [] else head rest : every n (tail rest)
where rest = drop (n-1) xs
(It's more limited because it has an unnecessary Eq a
constraint.)