更具体地说,如何从现有的无限列表生成每第N个元素的新列表?
例如,如果列表是[5, 3, 0, 1, 8, 0, 3, 4, 0, 93, 211, 0 ...]
,那么获取每3个元素将导致这个列表[0,0,0,0,0 ...]
更具体地说,如何从现有的无限列表生成每第N个元素的新列表?
例如,如果列表是[5, 3, 0, 1, 8, 0, 3, 4, 0, 93, 211, 0 ...]
,那么获取每3个元素将导致这个列表[0,0,0,0,0 ...]
使用drop的我的版本:
every n xs = case drop (n-1) xs of
y : ys -> y : every n ys
[] -> []
编辑:这个方法同样适用于有限列表。对于仅限于无限列表的情况,Charles Stewart提供的解决方案略微更短。
我在工作中没有任何测试的东西,但是类似这样的代码:
extractEvery m = map snd . filter (\(x,y) -> (mod x m) == 0) . zip [1..]
应该即使在无限列表上也能正常工作。
(编辑:已测试并更正。)
从第一个元素开始:
everyf n [] = []
everyf n as = head as : everyf n (drop n as)
从第n个元素开始:
every n = everyf n . drop (n-1)
everyf n = map head . takeWhile (not . null) . iterate (drop n)
或 every n = map head . takeWhile (not . null) . iterate (drop n) . drop (n-1)
。 - ephemient. drop (n-1)
而不是 (drop (n-1) as)
让代码更加优雅易读,我现在已经在我的答案中使用了它... :) - sthf l n = [l !! i | i <- [n-1,n-1+n..]]
l
在内存中保留-防止l
被垃圾收集器回收,使其短暂存在并根本不分配。 - Will NessMHarris的答案很好。但我喜欢避免使用\
,所以这是我的高尔夫球:
extractEvery n
= map snd . filter fst
. zip (cycle (replicate (n-1) False ++ [True]))
n-1
开始而不是从索引0
开始,可以使用以下代码:cycle $ replicate (n-1) False ++ [True]
。其中replicate (n-1) False
表示将False
元素复制(n-1)
次,然后通过++ [True]
在末尾添加一个True
元素。最后使用cycle
函数将结果重复循环。 - ephemient另一种去除mod
的解决方案:
extractEvery n = map snd . filter ((== n) . fst) . zip (cycle [1..n])
mod
和==
有什么区别?仍在进行可预测结果的测试...我不认为你今天会像这样编码。 :) - Will Ness前几天我把我的Haskell版本删掉了,因此尚未经过测试,但以下代码似乎比其他代码简单一些(利用模式匹配和drop函数避免使用zip和mod):
everynth :: Int -> [a] -> [a]
everynth n xs = y : everynth n ys
where y : ys = drop (n-1) xs
takeEveryM m lst = [n | (i,n) <- zip [1..] lst, i `mod` m == 0]
另一个:
import Data.List
takeEveryMth m =
(unfoldr g) . dr
where
dr = drop (m-1)
g (x:xs) = Just (x, dr xs)
g [] = Nothing
every n xs = map (xs!!) [n-1,n-1+n..]
为了让读者不必担心 i 是什么,建议使用以下代码而非 JA 的列表推导式。但无论哪种方式,都需要 O(n^2) 的时间复杂度,而实际上可以优化到 O(n),因此也许以下代码更好:
every n = map (!!(n-1)) . iterate (drop n)
!!
,一次是为了 drop
);ephemient 对 sth 的答案的评论给出了这类问题的最佳解决方案,通过“滑动”列表并使用 map head
。 - Nefrubyr
takeEvery
或takeNth
;不幸的是,在其他各种语言中,这两个名称均指始终包括第一个元素并仅从第 N 个元素开始跳过的版本。不确定如何最好地区分这些意图的名称。 - Mark Reed[] -> []
使用模式匹配,当drop (n-1) xs
返回一个空列表时返回一个空列表。 - Victor Johnson[] -> []
之前应该是(y:ys) -> y : every n ys
。 - Victor Johnson