2015-02-13 2 views
2

Я это Data.TextКак синтаксический анализ текста и извлекать целое

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

Как извлечь число из этого текста и применить функцию к ним?

+0

как строка или 'IO' монада? –

+0

его текст, который я получаю как параметр в запросе http получить – custosat

+0

Итак, функция - это слово? Есть ли способ изолировать 'max', ... Каковы спецификации? –

ответ

-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 
+0

OP сказал «Data.Text». – dfeuer

+0

@dfeuer: если человек может представить Data.Text без 'распаковки'. Полагает, что это справедливо только в эпоху до Google, но в любом случае ... –

+0

@dfeuer: тогда вы теперь можете использовать другой ответ ...; P –

0

Этот пример кода показывает простой способ сделать это:

import Data.List 
import Control.Monad 

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

Downvoter отмечает, что вопрос касается 'Text', а не' String'. – dfeuer

+0

@vikingsteve: была та же проблема. Очень важно, конечно ... Особенно, если вы предоставляете несколько номеров ... –

+0

Хорошо, спасибо. Будет ли «Data.Text.unpack» использоваться для работы со строковыми функциями, например. 'слова'? – vikingsteve

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 
+0

Вы * почти * получите upvote здесь. Остаются две проблемы: 1. Нет причин использовать 'signed', если вы отфильтровываете знаки. 2. Кажется, что намного больше Haskellian заменяет «либо (ошибка.show) fst' с 'fmap fst' и окончательной' map' с 'mapM' или' traverse'. – dfeuer

+1

И (3), он не вычисляет максимум, который после всего вопроса о OP. –

+0

@CommuSoft, хорошая точка. Это просто требует выполнения другой функции, чтобы сделать 'fmap maximum'. – dfeuer

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 
Смежные вопросы