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

后端 未结 23 1280
再見小時候
再見小時候 2020-12-04 23:58

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

相关标签:
23条回答
  • 2020-12-05 00:40

    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
    
    0 讨论(0)
  • 2020-12-05 00:40

    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.

    0 讨论(0)
  • 2020-12-05 00:43

    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.

    0 讨论(0)
  • 2020-12-05 00:43

    Alternate solution to get rid of mod:

    extractEvery n = map snd . filter ((== n) . fst) . zip (cycle [1..n])
    
    0 讨论(0)
  • 2020-12-05 00:44

    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
    
    0 讨论(0)
  • 2020-12-05 00:46

    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)
    
    0 讨论(0)
提交回复
热议问题