例如,我需要一个函数:
gather :: Int -> [a] -> [[a]]
gather n list = ???
其中gather 3 "Hello!" == ["Hel","ell","llo","ol!"]
。
我有一个有效的实施方案:
gather :: Int-> [a] -> [[a]]
gather n list =
unfoldr
(\x ->
if fst x + n > length (snd x) then
Nothing
else
Just
(take
n
(drop
(fst x)
(snd x)),
(fst x + 1, snd x)))
(0, list)
但我想知道这种语言中是否已经内置了一些东西?我扫描了Data.List但没有看到任何内容。
答案 0 :(得分:14)
您可以使用tails
:
gather n l = filter ((== n) . length) $ map (take n) $ tails l
或使用takeWhile
代替filter
:
gather n l = takeWhile ((== n) . length) $ map (take n) $ tails l
编辑:您可以按照评论中的建议删除从n
返回的列表的最后tails
个元素,从而删除过滤器步骤:
gather n = map (take n) . dropLast n . tails
where dropLast n xs = zipWith const xs (drop n xs)
答案 1 :(得分:5)
由于拉链的属性,可以自动安排尾部掉落,
import Data.List (tails)
g :: Int -> [a] -> [[a]]
g n = foldr (zipWith (:)) (repeat []) . take n . tails
或者简单的transpose . take n . tails
就足够了。测试:
Prelude Data.List> g 3 [1..10]
[[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,7],[6,7,8],[ 7,8,9],[8,9,10]] Prelude Data.List>转置。拿3。尾巴$ [1..10]
[[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,7],[6,7,8],[ 7,8,9],[8,9,10],[9,10],[10]]
(编辑2018-09-16:)使用压缩可以用更高级别来表达traverse ZipList
:
g :: Int -> [a] -> [[a]]
g n = getZipList . traverse ZipList . take n . tails