我遇到一些元素列表xs
非常常见,并希望对每个第N个元素做一些事情。最简单的例子是Sieve或Erastothenes,你想要“敲掉”给定素数的每一个倍数。我可以这样做的两种方法是通过计数器变量传递显式递归;或zipWith ($) (cycle (replicate (n-1) id ++ f))
。那么哪种方式更好/更优雅/更常用,或者是否有一些我找不到的像mapEveryN :: (a -> a) -> Int -> [a] -> [a]
这样的库函数?
答案 0 :(得分:2)
正如你和bheklilr所说,cycle
提供了一个很好的方法来实现这一目标。你可以稍微利用懒惰:
mapEvery :: Int -> (a -> a) -> [a] -> [a]
mapEvery n f = zipWith ($) (drop 1 . cycle . take n $ f : repeat id)
zipWith
和cycle
的使用似乎更加惯用(复杂的行为由更简单的行为组成),而不是手写的递归函数,它结合了两个任务。
注意:tail
此处为n = 0
定义了此函数,因此最好drop 1
。
我不知道这是一个图书馆功能。