parsing - 使用 attoparsec 递归返回 .txt 文件中的所有单词
问题描述
我对 Haskell 相当陌生,我刚刚开始学习如何使用 attoparsec 从 .txt 文件中解析大量英文文本。我知道如何在不使用 attoparsec 的情况下获取 .txt 文件中的单词数,但我有点坚持使用 attoparsec。当我在下面运行我的代码时,假设
“Hello World,我是 Elliot Anderson。\n我是 Mr.Robot。\n”
我只回来了:
世界,我是艾略特·安德森。\n我是 Mr.Robot。\n" (散文 {word = "Hello"})
这是我当前的代码:
{-# LANGUAGE OverloadedStrings #-}
import Control.Exception (catch, SomeException)
import System.Environment (getArgs)
import Data.Attoparsec.Text
import qualified Data.Text.IO as Txt
import Data.Char
import Control.Applicative ((<*>), (*>), (<$>), (<|>), pure)
{-
This is how I would usually get the length of the list of words in a .txt file normally.
countWords :: String -> Int
countWords input = sum $ map (length.words) (lines input)
-}
data Prose = Prose {
word :: String
} deriving Show
prose :: Parser Prose
prose = do
word <- many' $ letter
return $ Prose word
main :: IO()
main = do
input <- Txt.readFile "small.txt"
print $ parse prose input
另外,以后如何获得单词的整数计数?此外,有关如何开始使用 attoparsec 的任何建议?
解决方案
你已经有了一个很好的开始——你可以解析一个单词。
接下来你需要的是 a Parser [Prose]
,它可以通过将你的prose
解析器与另一个消耗“非散文”部分的解析器组合来表达,使用sepBy
or ,你可以在文档sepBy1
中查找。Data.Attoparsec.Text
从那里,获取字数的最简单方法是简单地获取您所获得的长度[Prose]
。
编辑:
这是一个最小的工作示例。Parser
runner 已被交换parseOnly
以允许忽略剩余输入,这意味着尾随的非单词不会使解析器变得疯狂。
{-# LANGUAGE OverloadedStrings #-}
module Atto where
--import qualified Data.Text.IO as Txt
import Data.Attoparsec.Text
import Control.Applicative ((*>), (<$>), (<|>), pure)
import qualified Data.Text as T
data Prose = Prose {
word :: String
} deriving Show
optional :: Parser a -> Parser ()
optional p = option () (try p *> pure ())
-- Modified to disallow empty words, switched to applicative style
prose :: Parser Prose
prose = Prose <$> many1' letter
separator :: Parser ()
separator = many1 (space <|> satisfy (inClass ",.'")) >> pure ()
wordParser :: String -> [Prose]
wordParser str = case parseOnly wp (T.pack str) of
Left err -> error err
Right x -> x
where
wp = optional separator *> prose `sepBy1` separator
main :: IO ()
main = do
let input = "Hello World, I am Elliot Anderson. \nAnd I'm Mr.Robot.\n"
let words = wordParser input
print words
print $ length words
提供的解析器不会给出完全相同的结果,concatMap words . lines
因为它也会中断.,'
. 修改此行为只是一个简单的练习。
希望能帮助到你!:)
推荐阅读
- python - Flask restplus SQL 查询输出格式
- python - 在 H2o 中计算 MAPE:错误:提供的列类型 POSIXct 未知
- java - 会话超时延长请求和响应之间的延迟
- c++ - cmake force config=为库发布
- powershell - 无法使用 Get-MessageTrackingLog 将外部电子邮件收件人列表导出为 Sender@domain.com.CSV?
- dart - 如何在颤动中制作像谷歌地图这样的可滚动小部件?
- javascript - 如何使用 javascript 在本地保存/更新 HTML 页面?
- javascript - 从 React 组件创建 HTML 文件
- r - 用 ggplot2 绘制多边形 shapefile 会混淆多边形
- ios - 为良好的动态 iOS 应用程序获取错误“与企业一起配置失败”