首先,讓我們獲得Windows結尾沒有擔心短期的:
import Data.List (tails)
windows' :: Int -> [a] -> [[a]]
windows' n = map (take n) . tails
> windows' 3 [1..5]
[[1,2,3],[2,3,4],[3,4,5],[4,5],[5],[]]
現在,我們要擺脫短的人的不檢查長度每一個。
因爲我們知道他們是在年底,我們可能會失去他們這樣的:
windows n xs = take (length xs - n + 1) (windows' n xs)
但是,這不是偉大的,因爲我們仍然要經過XS一個額外的時間來獲得它的長度。它也不適用於您的原始解決方案所實現的無限列表。
而是讓我們寫一個函數使用一個列表作爲標尺測量量從另取:
takeLengthOf :: [a] -> [b] -> [b]
takeLengthOf = zipWith (flip const)
> takeLengthOf ["elements", "get", "ignored"] [1..10]
[1,2,3]
現在我們可以這樣寫:
windows :: Int -> [a] -> [[a]]
windows n xs = takeLengthOf (drop (n-1) xs) (windows' n xs)
> windows 3 [1..5]
[[1,2,3],[2,3,4],[3,4,5]]
作品的無限列表太:
> take 5 (windows 3 [1..])
[[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,7]]
正如加布裏埃爾岡薩雷斯所說,時間複雜性是沒有更好的,如果你想使用整個結果。但是如果你只使用一些窗口,我們現在設法避免在你不使用的窗口上執行take
和length
的工作。
或'foldr(zipWith(:))(repeat [])。以m。 tails'。 –
@Will Ness - 哦,那很好 – user1441998
@ user1441998這就是'ZipList'上的'sequenceA'正在做的事情。 :)(通過「或」我的意思是「或者可以明確地寫出......」)。 ['sequenceA'](http://hackage.haskell.org/package/base-4.8.1.0/docs/src/Data.Traversable.html#sequenceA)== ['foldr((<*>)。((:) <$>))(pure [])'](http://hackage.haskell.org/package/base-4.8.1.0/docs/src/Data.Traversable.html#line-177)。 –