How to select every nth item from a list

Possible duplicate:
How to get every Nth element of an infinite list in Haskell?

The simple task is that we have a list and we want to leave only every nth element in this list. What is the most idiomatic way to do this in haskell?

from the top of the head this is something like:

dr n [] = [] dr n (x : xs) = x : (dr n $ drop n xs) 

but I have a strong feeling that I'm exaggerating the problem.

+5
source share
4 answers

Your solution is fine, but here are three other solutions using functions from the Haskell core library.

 dr1 m = concatMap (take 1) . iterate (drop m) 

Roughly, it will never stop (because iterate never ends). Therefore, perhaps the best solution would be to use unfoldr :

 {-# LANGUAGE TupleSections #-} import Data.Maybe dr2 m = unfoldr ((\x-> fmap (,drop mx) (listToMaybe x))) 

The function that you pass in for deployment can become a little ugly if you don't know the GHC extensions and concepts like functors, here this solution again without fancy work (unverified):

 dr2 m = unfoldr ((\x -> case listToMaybe x of Nothing -> Nothing Just i -> Just (i,drop mx))) 

If you don't like sweeps then consider a zip and a filter:

 dr3 m = map snd . filter ((== 1) . fst) . zip (cycle [1..m]) 

Overview

Understanding all of these decisions is somewhat different. Learning why you will make the best Haskell program. dr1 uses iteration and thus never ends (maybe this is normal for infinite lists, but probably not a good general solution):

 > dr1 99 [1..400] [1,100,199,298,397^CInterrupted. 

The dr2 solution will show each m th value, skipping the values ​​in the sweep. The expansion passes both the value that will be used for the next expansion and the result of the current expansion in one tuple.

 > dr2 99 [1..400] [1,100,199,298,397] 

dr3 solution dr3 little longer, but it may be easier to understand for beginners. First, you mark each item in the list with a loop [1..n, 1..n, 1..n ...] . Secondly, you select only numbers with tags 1 , effectively skipping n-1 elements. Third, you remove the tags.

 > dr3 99 [1..400] [1,100,199,298,397] 
+10
source

My option would be:

 each :: Int -> [a] -> [a] each n = map head . takeWhile (not . null) . iterate (drop n) 

He plays fast and well with laziness.

+14
source

Many ways to shave this yak! Here's another one:

 import Data.List.Split -- from the "split" package on Hackage dr n = map head . chunk n 
+8
source

Try the following:

 getEach :: Int -> [a] -> [a] getEach _ [] = [] getEach n list | n < 1 = [] | otherwise = foldr (\i acc -> list !! (i - 1):acc) [] [n, (2 * n)..(length list)] 

Then in the GHC:

 *Main> getEach 2 [1..10] [10,8,6,4,2] 
0
source

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


All Articles