您的代码几乎可以:
maxL = maximum [length e | e <- entries]
runs = [r | r <- [e | e <- entries, length e == i]] where i = [1..maxL]
除非那样where
做。它不是 ; 的同义词foreach
。但对于let
:
runs = let i = [1..maxL]
in [r | r <- [e | e <- entries, length e == i]]
所以,length e
是一个整数,但是i
是一个整数[1..maxL]
列表。您打算一一i
接受这些值,这是通过在列表理解中绑定来完成的:[1..maxL]
<-
runs = [ [r | r <- [e | e <- entries, length e == i]] | i <- [1..maxL]]
现在,[r | r <- xs]
与 just 相同xs
,因此变为
runs = [ [e | e <- entries, length e == i] | i <- [1..maxL]]
使用“标准”功能,这被写成
import Data.List (sortBy)
import Data.Ord (comparing)
runs = group $ sortBy (comparing length) entries
它在算法上也更好。虽然,对于不存在的长度,它不会有空运行,所以两者并不是严格等价的。但这可以通过另一个O(n)
结果来解决,
-- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
runs' = snd $ mapAccumL
(\a@ ~((k,g):t) i-> if null a || i<k then (a,[]) else (t,g))
[ (length $ head g, g) | g<- runs]
[ 1..maxL]