List 无跨步功能
我最近需要跨越一个列表,以便只窥视一些元素。这算是一个过滤函数,但并不是那么简单。但首先,这是一个跨越 跨距列表(或任何可遍历类型)与折叠列表相同,但会丢弃一些经常遇到的元素(关于跨距值)。我们拾取一个元素,然后要拾取的下一个值将是下一个值。例如,如果我们在跨步值设置为0的情况下对列表进行跨步,那么实际上会使列表保持不变。如果我们跨过一个列表,我们得到两个元素中的一个:List 无跨步功能,list,haskell,List,Haskell,我最近需要跨越一个列表,以便只窥视一些元素。这算是一个过滤函数,但并不是那么简单。但首先,这是一个跨越 跨距列表(或任何可遍历类型)与折叠列表相同,但会丢弃一些经常遇到的元素(关于跨距值)。我们拾取一个元素,然后要拾取的下一个值将是下一个值。例如,如果我们在跨步值设置为0的情况下对列表进行跨步,那么实际上会使列表保持不变。如果我们跨过一个列表,我们得到两个元素中的一个: stride 0 [1..10] == [1..10] stride 1 [1..10] == [1,3,5,7,9] str
stride 0 [1..10] == [1..10]
stride 1 [1..10] == [1,3,5,7,9]
stride 2 [1..10] == [1,4,7,10]
我查看了数据.列表
,没有发现任何可以跨越列表的内容。这就是为什么我写了一个函数来跨越我的——和你的!——材料:
import Data.DList
-- for Data.List
stride :: (Num a, Eq a) => a -> [b] -> [b]
stride s = toList . snd . foldl (\(sa,xa) x -> if sa == s then (0,xa `snoc` x) else (sa+1,xa)) (s,fromList [])
你可以像上面那样使用它。
是否可以提议将其作为
数据列表
模块的一部分?我认为它会有很大帮助。此函数并不能完全满足您的需要,但您可以将stride
函数建立在它的基础上:
chunksOf :: Int -> [a] -> [[a]]
chunksOf n = takeWhile (not . null) . map (take n) . iterate (drop n)
现在,您的步幅函数可能如下所示:
stride :: Int -> [a] -> [a]
stride n = map head . chunksOf (n + 1)
在这里使用
head
很好,因为takeWhile(not.null)
确保子列表永远不能为空。此函数不能完全满足您的需要,但您可以将stride
函数建立在它的基础上:
chunksOf :: Int -> [a] -> [[a]]
chunksOf n = takeWhile (not . null) . map (take n) . iterate (drop n)
现在,您的步幅函数可能如下所示:
stride :: Int -> [a] -> [a]
stride n = map head . chunksOf (n + 1)
在这里使用
head
很好,因为takeWhile(not.null)
确保子列表永远不能为空。一个同样适用于无限列表且效率更高的简单实现是
stride :: Int -> [a] -> [a]
stride s = go
where
go (x:xs) = x : go (drop s xs)
go _ = []
如果您想将其用于除Int
以外的其他类型,请使用它
import Data.List
stride :: Integral i => i -> [a] -> [a]
stride s = go
where
go (x:xs) = x : go (genericDrop s xs)
go _ = []
在我看来,对非整数类型这样做毫无意义
是否可以提议将其作为数据列表
模块的一部分
是的,那是可能的,就libraries@haskell.org邮件列表
然而,我认为它不会被接受。有用性太小,无法将其添加到
base
包中。最好将其添加到另一个包中。也许将其包含在中是最好的。一个更简单的实现,也可以在无限列表上工作,并且效率更高
stride :: Int -> [a] -> [a]
stride s = go
where
go (x:xs) = x : go (drop s xs)
go _ = []
如果您想将其用于除Int
以外的其他类型,请使用它
import Data.List
stride :: Integral i => i -> [a] -> [a]
stride s = go
where
go (x:xs) = x : go (genericDrop s xs)
go _ = []
在我看来,对非整数类型这样做毫无意义
是否可以提议将其作为数据列表
模块的一部分
是的,那是可能的,就libraries@haskell.org邮件列表
然而,我认为它不会被接受。有用性太小,无法将其添加到base
包中。最好将其添加到另一个包中。也许最好将其包含在中。或者使用该软件包,您可以:
>stridingOf l n = (elementsOf l ((==0) . (flip mod (n + 1))))
>striding = stridingOf traverse
>stride n = toListOf striding
>stride 1 [1..10]
[1,3,5,7,9]
编写stridingOf而不是仅仅是striding的一点额外工作允许在文本和ByTestRing上轻松使用,并且在没有软件包的情况下重写要困难得多
#镜头或者使用该软件包,您可以:
>stridingOf l n = (elementsOf l ((==0) . (flip mod (n + 1))))
>striding = stridingOf traverse
>stride n = toListOf striding
>stride 1 [1..10]
[1,3,5,7,9]
编写stridingOf而不是仅仅是striding的一点额外工作允许在文本和ByTestRing上轻松使用,并且在没有软件包的情况下重写要困难得多
#镜头没错
chunksOf
是可以添加的函数,stride
可以基于它。chunksOf
的另一种实现可以在这篇博文中找到:我总是说:寻找组合解决方案。我特别喜欢这种方法,因为它使用了构图。Daniel的实现和您的实现都没有利用这一点。编辑:这也确保了它是适当的懒惰。毫无疑问,您的chunksOf
实现是优雅的!这正是我在写我的博客文章时所寻找的(但找不到,请看“未来工作”评论)。这是一个展开器<代码>chunksOf n=takeWhile(非.null)。unbover(Just.splitAt n)您实际上可以通过以下简短的代码片段来实现stride
本身的unbover
,但我并不喜欢它:stride n=unbover(\xs'->dox:xs完全正确!chunksOf
是可以添加的函数,而stride
可以基于它。在这篇博文中可以找到chunksOf
的另一种实现:我总是说:使用组合解决方案。我特别喜欢这种方法,因为它使用了组合。Dani和Dani都不喜欢el的实现和你的实现都没有利用它。编辑:这也确保了它是适当的懒惰。毫无疑问,你对chunksOf
的实现是优雅的!这正是我在写我的博客文章时所寻找的(并且找不到,请参阅“未来工作”备注)。这是一个展开器!chunksOf n=takeWhile(not.null)。展开器(Just.splitAt n)
您实际上可以通过以下简短的代码片段来实现stride
本身的unfover
,但我并不喜欢它:stride n=unfover(\xs'->do x:xs好吧,它对RealFrac
s来说是有意义的,基本上是一个更高效的\s l->[l!!round x | x这样的东西可能确实有意义,我没有想到。如果你看一下链接的实现,它从0开始一步一步地计数,直到sa==s
,如果s
是整数,它只会产生比初始元素更多的元素。哇,忘了drop
函数,好主意:)嗯,这对于RealFrac
s是有意义的,它基本上是一个更高效的\s l->[l!!round x | x这样的东西可能确实有意义,我没有想到。如果你看一下链接的实现,它从0开始一步一步地计数,直到sa==s
,如果s
是整数,它只会产生比初始元素更多的元素。哇,忘了drop
函数,好主意:)为什么不使用stride n xs=chunk(n+1)xs>>=take 1
?这几乎不是一个问题——这是唯一合适的问题