可能重复:
How to get every Nth element of an infinite list in Haskell?
简单的任务 - 我们有一个列表,并希望只留下该列表中的每个第n个元素。 在haskell中最常用的方法是什么?
脱离我的头顶,它是这样的:
dr n [] = []
dr n (x : xs) = x : (dr n $ drop n xs)
但我有一种强烈的感觉,我对这个问题过于复杂。
答案 0 :(得分:14)
我的变体是:
each :: Int -> [a] -> [a]
each n = map head . takeWhile (not . null) . iterate (drop n)
速度快,而且懒惰也很好。
答案 1 :(得分:10)
您的解决方案很好,但是这里有三个其他解决方案,使用Haskell基础库中的函数。
dr1 m = concatMap (take 1) . iterate (drop m)
粗略地说,这永远不会终止(因为iterate
永远不会终止)。因此,或许更好的解决方案是使用unfoldr
:
{-# LANGUAGE TupleSections #-}
import Data.Maybe
dr2 m = unfoldr ((\x-> fmap (,drop m x) (listToMaybe x)))
如果您不了解GHC扩展和诸如仿函数之类的概念,那么您传递给展开的函数会变得有点难看,这里的解决方案再次没有花哨的脚步(未经测试):
dr2 m = unfoldr ((\x -> case listToMaybe x of
Nothing -> Nothing
Just i -> Just (i,drop m x)))
如果您不喜欢展开,请考虑使用拉链和滤镜:
dr3 m = map snd . filter ((== 1) . fst) . zip (cycle [1..m])
查看强>
了解所有这些解决方案略有不同。学习为什么会让你成为一个更好的Haskell程序员。 dr1
使用iterate,因此永远不会终止(也许这对于无限列表来说是可以的,但可能不是一个好的整体解决方案):
> dr1 99 [1..400]
[1,100,199,298,397^CInterrupted.
dr2
解决方案将通过跳过展开中的值来显示每个m
值。展开传递将用于下一次展开的值和当前展开的结果在单个元组中。
> dr2 99 [1..400]
[1,100,199,298,397]
dr3
解决方案稍长,但初学者可能更容易理解。首先,您使用[1..n, 1..n, 1..n ...]
的周期标记列表中的每个元素。其次,您只选择标有1
的数字,有效地跳过n-1
元素。第三,你删除标签。
> dr3 99 [1..400]
[1,100,199,298,397]
答案 2 :(得分:8)
有很多方法可以剃掉这只牦牛!这是另一个:
import Data.List.Split -- from the "split" package on Hackage
dr n = map head . chunk n
答案 3 :(得分:0)
试试这个:
getEach :: Int -> [a] -> [a]
getEach _ [] = []
getEach n list
| n < 1 = []
| otherwise = foldr (\i acc -> list !! (i - 1):acc) [] [n, (2 * n)..(length list)]
然后在GHC:
*Main> getEach 2 [1..10]
[10,8,6,4,2]