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

¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top