Frage

Ich versuche, große TSV-Dateien mit JSON in der 5. Spalte für den Import in MongoDB geeignet zu machen.Insbesondere möchte ich die Schlüsselfelder der obersten Ebene und nur der obersten Ebene in _id ändern.Das habe ich bisher, es scheint zu funktionieren, ist aber langsam:

{-# 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

Laut Profiler werden 58,7% der Zeit in Klammern verbracht, 19,6% in keyTo_id, 17,1% in main.

Sicherlich gibt es eine bessere Möglichkeit, eingeklammerte Begriffe unverändert zurückzugeben, wenn die Klammern übereinstimmen?

Ich habe mir kurz attoparsec-conduit angesehen, aber ich habe keine Ahnung, wie ich diese Bibliothek verwenden soll, und kann nicht einmal sagen, ob dies die Art von Dingen ist, für die sie verwendet werden kann.

BEARBEITEN:Den Code aktualisiert.Die Daten stammen von openlibrary.org , e.g. http://openlibrary.org/data/ol_dump_authors_latest.txt.gz

War es hilfreich?

Lösung

Verwenden Sie die scan Funktion.Es ermöglicht Ihnen, über eine Zeichenfolge zu scannen, die einen Status verwaltet.In Ihrem Fall ist der Status eine Zahl - der Unterschied zwischen dem Öffnen und Schließen von Klammern, auf den Sie bisher gestoßen sind.Wenn Ihr Status 0 ist, bedeutet dies, dass geschweifte Klammern innerhalb der aktuellen Teilzeichenfolge übereinstimmen.

Der Trick ist, dass Sie die Saite nicht auf diese Weise dekonstruieren und rekonstruieren, also sollte sie schneller sein.

Außerdem könnten Sie auch mit Ihrem aktuellen Algorithmus etwas Leistung erzielen, indem Sie Lazy Text verwenden - the concat funktion würde effizienter arbeiten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top