如何从列表中选择每个第n个元素 [英] How to select every n-th element from a list
问题描述
简单任务 - 我们有一个列表,并且只想在列表中留下每个第n个元素。
在haskell中最习惯的方式是什么?
关闭我的头顶部,就像这样:
dr n [] = []
dr n(x:xs)= x:(dr n $ drop n xs)
但我有一种强烈的感觉,我正在过度复杂化这个问题。
您的解决方案很好,但是这里有三个使用Haskell基础库函数的解决方案。 code> dr1 m = concatMap(取1)。 iterate(drop m)
粗略的说,它不会终止(因为 iterate
永不终止)。所以也许更好的解决方案是使用 unfoldr
:
{ - #(语法TupleSections# - )
导入Data.Maybe
dr2 m = unfoldr((\ x-> fmap(,drop mx)(listToMaybe x)))
如果您不知道GHC扩展和概念(如函子),那么传递给展开的函数会变得有点难看,下面是该解决方案(未经测试):
dr2 m = unfoldr((\ x - > case listToMaybe x
Nothing - > Nothing
Just i - > Just(i,drop mx)))
如果您不喜欢展开,请考虑使用zip和过滤器:
dr3 m =地图snd。过滤器((== 1).fst)。 zip(周期[1..m])
评论
了解所有这些解决方案略有不同。学习为什么会让你成为更好的Haskell程序员。 dr1
使用迭代,因此永远不会终止(也许这对无限列表是可以的,但可能不是一个好的整体解决方案):
> dr1 99 [1..400]
[1,100,199,298,397 ^ C中断。
dr2
解决方案将显示每个 m
th值通过跳过展开的值。展开会将用于下一个展开的值和当前展开的结果传递给单个元组。
> ; 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]
Possible Duplicate:
How to get every Nth element of an infinite list in Haskell?
Simple task - we have a list and want to leave only each nth element in that list. What is the most idiomatic way to do it in haskell?
off the top of my head it is something like:
dr n [] = []
dr n (x : xs) = x : (dr n $ drop n xs)
but I have a strong feeling that I'm overcomplicating the problem.
Your solution is fine, but here are three other solutions using functions from Haskell's base library.
dr1 m = concatMap (take 1) . iterate (drop m)
Of coarse, this will never terminate (because iterate
never terminates). So perhaps a better solution would be to use unfoldr
:
{-# LANGUAGE TupleSections #-}
import Data.Maybe
dr2 m = unfoldr ((\x-> fmap (,drop m x) (listToMaybe x)))
The function you pass to an unfold can get a bit ugly if you don't know GHC extensions and concepts such as functors, here's that solution again without the fancy foot-work (untested):
dr2 m = unfoldr ((\x -> case listToMaybe x of
Nothing -> Nothing
Just i -> Just (i,drop m x)))
If you don't like unfolds then consider a zip and a filter:
dr3 m = map snd . filter ((== 1) . fst) . zip (cycle [1..m])
Review
Understand all these solutions are slightly different. Learning why will make you a better Haskell progammer. dr1
uses iterate and will thus never terminate (perhaps this is ok for infinite lists, but probably not a good overall solution):
> dr1 99 [1..400]
[1,100,199,298,397^CInterrupted.
The dr2
solution will show every m
th value by skipping values in the unfold. The unfold passes both the value to be used for the next unfolding and the result of the current unfolding in a single tuple.
> dr2 99 [1..400]
[1,100,199,298,397]
The dr3
solution is slightly longer but probably easier for a beginner to understand. First you tag every element in the list with a cycle of [1..n, 1..n, 1..n ...]
. Second, you select only the numbers tagged with a 1
, effectively skipping n-1
of the elements. Third you remove the tags.
> dr3 99 [1..400]
[1,100,199,298,397]
这篇关于如何从列表中选择每个第n个元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!