Domanda

Sto cercando di creare grandi file TSV con JSON nella 5a colonna adatto per l'importazione a MongoDB. In particolare, voglio cambiare il livello superiore e solo i campi chiave di livello superiore a _id.Questo è quello che ho finora, sembra funzionare ma è 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
.

Secondo il profiler 58,7% del tempo è trascorso nella staffa, 19,6% in Keyto_ID, 17,1% nel principale.

Sicuramente c'è un modo migliore per restituire i termini brackettati invariati se le staffe corrispondono?

Guardò brevemente Attoparsec-Conduit, ma non ho idea di come usare quella biblioteca e non riesco nemmeno a dire se questo è il genere di cose per cui può essere usato.

Modifica: aggiornato il codice.I dati provengono da OpenLibrary.org, E.g. http://openlibrary.org/data/ol_dump_authors_latest.txt.gz

È stato utile?

Soluzione

Utilizzare la funzione scan.Ti consente di eseguire la scansione su una stringa che mantiene uno stato.Nel tuo caso lo stato sarà un numero - la differenza di apertura e chiusura bretelle che hai incontrato finora. Quando il tuo stato è 0, significa che le bretelle corrispondono all'interno della sottostringa corrente.

Il trucco è che non decostruisci e ricostruisci la stringa in questo modo, quindi dovrebbe essere più veloce.

Inoltre, è possibile ottenere alcune prestazioni anche con il tuo attuale algoritmo utilizzando il testo pigro - la funzione concat funzionerebbe in modo più efficiente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top