您的解决方案很好,但这里有其他三个使用 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)))
如果您不喜欢展开,请考虑使用 zip 和过滤器:
dr3 m = map snd . filter ((== 1) . fst) . zip (cycle [1..m])
评论
了解所有这些解决方案都略有不同。学习为什么会让你成为一个更好的 Haskell 程序员。 dr1 使用迭代,因此永远不会终止(也许这对于无限列表是可以的,但可能不是一个好的整体解决方案):
> dr1 99 [1..400]
[1,100,199,298,397^CInterrupted.
dr2 解决方案将通过跳过展开中的值来显示每个 mth 值。展开将用于下一次展开的值和当前展开的结果都传递到单个元组中。
> 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]