如何在Haskell中实现获取文本文件最后10行的功能
Haskell实现tail取文本最后10行的方案
现有代码的快速修改
你目前的写法调用take 10是从行列表头部取元素,自然得到前10行。最简单的修改是先反转行列表、取前10个再反转回原顺序,代码如下:
getLastTenLines :: String -> String getLastTenLines s = unlines . reverse . take 10 . reverse . lines $ s
这个方案仅适合小文件使用,因为两次reverse操作需要加载整个文本到内存,处理大文件时性能和内存占用都会非常差。
大文件场景最优实现
类Unix系统的tail命令核心逻辑是维护固定长度的滚动缓冲区,遍历内容时仅保留最近的N行,内存占用恒定不受文件大小影响,Haskell中可以用性能优异的Sequence数据结构实现该逻辑:
import Data.Foldable (toList) import Data.Sequence (Seq(..), (|>), drop, length) -- 通用取最后N行函数 getLastNLines :: Int -> String -> String getLastNLines n = unlines . toList . foldl updateBuffer Empty . lines where updateBuffer buf line = let newBuf = buf |> line in if Data.Sequence.length newBuf > n then Data.Sequence.drop 1 newBuf else newBuf -- 封装为取最后10行 getLastTenLines :: String -> String getLastTenLines = getLastNLines 10
如果需要直接读取文件输出,搭配Haskell惰性IO的特性,不会一次性加载整个文件内容:
main :: IO () main = readFile "target.txt" >>= putStr . getLastTenLines
内容的提问来源于stack exchange,提问作者Ryan Harding
相关产品推荐
相关产品推荐

