Attoparsec:Saltando entre corchetes los términos?
-
13-12-2019 - |
Pregunta
Estoy tratando de hacer grandes TSV archivos con JSON en la 5ª columna adecuado para la importación de mongoDB.En particular, quiero cambiar de nivel superior y sólo la parte superior del nivel de los campos clave para _id.Esto es lo que tengo hasta ahora, parece que funciona pero es lento:
{-# LANGUAGE OverloadedStrings #-}
import System.Environment (getArgs)
import Data.Conduit.Binary (sourceFile, sinkFile)
import Data.Conduit
import qualified Data.Conduit.Text as CT
import qualified Data.Conduit.List as CL
import qualified Data.Text as T
import Data.Monoid ((<>))
import Data.Attoparsec.Text as APT
import Control.Applicative
main = do
(inputFile : outputFile : _) <- getArgs
runResourceT $ sourceFile inputFile
$= CT.decode CT.utf8 $= CT.lines $= CL.map jsonify
$= CT.encode CT.utf8 $$ sinkFile outputFile
jsonify :: T.Text -> T.Text
jsonify = go . T.splitOn "\t"
where
go (_ : _ : _ : _ : content : _) = case parseOnly keyTo_id content of
Right res -> res <> "\n"
_ -> ""
go _ = ""
keyTo_id :: Parser T.Text
keyTo_id = skipWhile(/='{') >> T.snoc <$>
(T.cons <$> (char '{')
<*> (T.concat <$> many1 ( bracket
<|> (string "\"key\":" >> return "\"_id\":")
<|> APT.takeWhile1(\x -> x /= '{' && x /= '}' && x/= '"')
<|> T.singleton <$> satisfy (/= '}')
)))
<*> char '}'
bracket :: Parser T.Text
bracket = T.cons <$> char '{'
<*> scan 1 test
where
test :: Int -> Char -> Maybe Int
test 0 _ = Nothing
test i '}'= Just (i-1)
test i '{' = Just (i+1)
test i _ = Just i
De acuerdo con el analizador de 58.7% de su tiempo se gasta en el soporte, el 19,6% en keyTo_id, el 17,1% en el principal.
Seguramente hay una mejor manera de regresar que figura entre corchetes los términos sin cambios si los soportes de coincidir?
Brevemente me miró attoparsec-conduit, pero no tengo idea de cómo utilizar la biblioteca y ni siquiera puedo decir si este es el tipo de cosa que puede ser utilizado para.
EDITAR:Actualizado el código.Los datos de openlibrary.org, e.g. http://openlibrary.org/data/ol_dump_authors_latest.txt.gz
Solución
El uso de la scan
la función.Permite escanear a través de una cadena de mantener un estado.En su caso, el estado será un número — la diferencia de apertura y cierre de llaves que te has encontrado hasta ahora.Cuando su estado es 0, que significa que los apoyos coincidir dentro de la corriente de la subcadena.
El truco es que usted no deconstruir y reconstruir la cadena de esta manera, así que debería ser más rápido.
También, usted podría ganar algo de rendimiento incluso con su actual algoritmo mediante perezoso Texto — la concat
función de trabajo de manera más eficiente.