3

mongoDBへのインポートに適した5列目のJSONを使用して大きなTSVファイルを作成しようとしています。特に、トップレベルとトップレベルのキーフィールドのみを_idに変更したいと思います。これは私がこれまでに持っているものです、それはうまくいくようですが遅いです:

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

プロファイラーによると、時間の58.7%がブラケットで、19.6%がkeyTo_idで、17.1%がメインで費やされています。

確かに、角かっこが一致する場合、角かっこで囲まれた用語を変更せずに返すより良い方法はありますか?

attoparsec-conduitを簡単に調べましたが、そのライブラリの使用方法がわからず、これが使用できる種類のものであるかどうかさえわかりません。

編集:コードを更新しました。データはopenlibrary.orgからのものです。例:http ://openlibrary.org/data/ol_dump_authors_latest.txt.gz

4

1 に答える 1

2

関数を使用しscanます。これにより、状態を維持する文字列をスキャンできます。あなたの場合、状態は数字になります—これまでに遭遇した中括弧の開閉の違いです。状態が0の場合、中括弧が現在のサブストリング内で一致することを意味します。

秘訣は、この方法で文字列を分解および再構築しないことです。したがって、より高速になるはずです。

また、レイジーテキストを使用することで、現在のアルゴリズムでもある程度のパフォーマンスを得ることができます。このconcat関数はより効率的に機能します。

于 2012-10-03T20:11:56.303 に答える