Haskell新手求助:实现读取文件去重后写入新文件的问题
解决Haskell文件去重行并写入的问题
问题描述
需要实现功能:读取输入文件内容,去除重复行后将唯一行写入输出文件。目前读取和去重逻辑存在偏差,写入环节也遇到类型不匹配问题。
现有代码的问题分析
两段尝试代码存在以下核心问题:
- 拆分函数误用:用
words contents拆分内容,words是按空白字符拆分单词,而非按行拆分,应该用lines来获取每行的字符串列表。 - 第一段代码的foldr错误:
writeFile类型为FilePath -> String -> IO (),每次调用会覆盖目标文件,且foldr的参数类型不匹配——无法将IO ()作为累加器传递。 - 第二段代码的类型不匹配:
writeFile的第二个参数要求是String,但直接传入了[String]类型的行列表,导致类型错误。
正确实现代码
import Data.List (nub) onlyUnique :: FilePath -> FilePath -> IO () onlyUnique inputFile outputFile = do -- 读取输入文件内容 contents <- readFile inputFile -- 按行拆分、去重、重新拼接成带换行的完整字符串 let fileLines = lines contents uniqueLines = nub fileLines outputContent = unlines uniqueLines -- 一次性写入输出文件 writeFile outputFile outputContent
代码说明
lines contents:将读取到的文件内容按换行符拆分为字符串列表,每个元素对应文件中的一行。nub fileLines:去除列表中的重复行,保留每行第一次出现的内容(注:nub是O(n²)复杂度,处理大文件时可改用Data.Set优化,比如Set.toList . Set.fromList fileLines)。unlines uniqueLines:将去重后的行列表重新拼接成完整字符串,每行末尾自动添加换行符,与lines是互逆操作。writeFile outputFile outputContent:一次性将拼接好的字符串写入输出文件,无需手动遍历或递归,writeFile会处理整个内容的写入逻辑。
额外说明
- 无需判断行列表是否为空:
unlines []会生成空字符串,writeFile写入空字符串会创建空文件,符合预期。 - 若无需保留行的原始出现顺序,用
Data.Set去重效率更高:
import qualified Data.Set as Set uniqueLines = Set.toList $ Set.fromList fileLines
内容的提问来源于stack exchange,提问作者Mon
相关产品推荐
相关产品推荐

