是否有内置函数来获取Haskell中列表大小n的所有连续子序列?

时间:2014-07-06 20:08:32

标签: haskell

例如,我需要一个函数:

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但没有看到任何内容。

2 个答案:

答案 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