我正在编写小函数来切断给定长度的数据包中的字符串,但我是Haskell的初学者,我想我可以简化我的功能。他们在这里:
packetAux _ [] = []
packetAux 0 ls = []
packetAux n l@(x:xs) = if n > (length l) then [] else x : packetAux (n - 1) xs
packet _ [] = []
packet 0 l = []
packet n l@(x:xs) = [x | x <- ((packetAux n l) : (packet n xs)), x /= ""]
Ex:包2“12345”给出[“12”,“23”,“34”,“45”]
我怎么能避免 1)packetAux和packet中的重复 2)用x / =“”过滤包中的结果?
答案 0 :(得分:5)
您的功能是
import Data.List (tails)
packets :: Int -> [a] -> [[a]]
packets n xs = filter ((==n).length) $ map (take n) $ tails xs
另一种写作方式是
packets n xs = foldr (zipWith (:)) (repeat []) $ take n $ tails xs
这两种变体实际上也会以无用的方式在无限列表上工作。
$
运算符只是为了便于分组而没有括号:
f $ g $ x = f ( g ( x ) )
答案 1 :(得分:2)
一般的诀窍是使用Hoogle或Hayoo!检查是否存在类似的功能。 数据包的签名是:
Int -> [Char] -> [[Char]]
如果您使用以上内容填写Hoogle,在第一批结果中您将获得具有非常相似签名的函数:
Int -> [a] -> [a]
它采用给定列表的“n”个第一个元素。
这将有助于我们减少功能的主要部分:
packet n (x:xs) = [[x] ++ take (n-1) xs] ++ packet n xs
现在,由于你不希望函数在列表长度小于n值时返回一个值,我们可以使用guards来保持简单:
packet n l@(x:xs)
| length l < n = []
| otherwise = [[x] ++ take (n-1) xs] ++ packet n xs
请注意,有可能通过减少对length函数的调用次数来提高速度。我们可以保留索引,而不是每次都调用它。但是,它显然意味着更多的代码......