如何解析Text并提取整数

时间:2015-02-13 19:10:13

标签: parsing haskell

我有Data.Text

"Check: Find max among: 70, 102, 271, 40"

如何从此文本中提取数字并对其应用函数?

5 个答案:

答案 0 :(得分:1)

您可以使用许多Haskell解析库来解析Text类型,但是对于这样一个简单的示例,我只需将其分解为单词,过滤数字并进行转换。正如dfeuer指出的那样,Haskell的String类型与其他答案使用的类型和您可能错误暗示的Text类型之间存在很大差异。对于文本类型,操作看起来非常相似,但您没有Prelude read操作:

import qualified Data.Text as T
import Data.Text (Text) 
import Data.Char (isDigit) 
import Data.Text.Read 

myRead :: Text -> [Int]
myRead = map num                 -- Convert the remaining elements into Ints
       . filter (not . T.null)   -- Drop all empty words
       . map (T.filter isDigit)  -- Drop all non-digits in each word (including signs!)
       . T.words                 -- Chop the string into words

num :: Text -> Int 
num = either (error . show) fst  -- Throw an exception if it wasn't a signed decimal
    . signed decimal             -- Read a signed decimal

答案 1 :(得分:0)

此代码示例显示了一种简单的方法:

import Data.List
import Control.Monad

getLine >>= \line -> putStrLn $ show $ maximum $ (map read . words $ filter (/=',') $ line :: [Int])

答案 2 :(得分:0)

出于各种美学原因,我喜欢这种方法:

import qualified Data.Text as T
import Data.Text.Read
import Data.Either
import Data.Char
import Data.Text.IO as T

readNums :: T.Text -> [Int]
readNums =
  map fst .                 -- 5. extract the parsed numbers
  snd .  partitionEithers . -- 4. collect only the valid numbers
  map decimal .             -- 3. parse each substring as an number
  filter (not . T.null) .   -- 2. filter out empty strings (not necessary)
  T.split (not . isDigit)   -- 1. split on non-digits

答案 3 :(得分:0)

这是适用于Text的单行解决方案。它将数字从Text中拉到带有 sepCap组合器,然后可以应用maximum函数。

由于这是一个解析器,因此您可以将其扩展到比本示例更复杂的内容,例如实际从字符串的第一部分解析查询指令。

import Replace.Megaparsec
import Text.Megaparsec
import Text.Megaparsec.Char.Lexer
import Data.Either
import Data.Maybe
import qualified Data.Text as T

maximum $ rights $ fromJust $ parseMaybe (sepCap (decimal :: Parsec Void T.Text Int)) 
    "Check: Find max among: 70, 102, 271, 40"
271

答案 4 :(得分:-2)

对于String,您可以使用:

maximum . map (read) . filter (all isDigit) . map (filter ((/=) ',')) words

或者对于Text,请使用:

import Prelude as P
import Data.Text as T

fString :: Text -> Integer
fString = maximum . P.map (read) . P.filter (all isDigit) . P.map (P.filter ((/=) ',')) . P.map (T.unpack) . T.words

然后,您可以编写main函数来读取stdin中的值。

main :: IO ()
main = do
    x <- getLine
    putStrLn $ show $ fString (pack x) --to demonstrate that it works with Data.Text