我正在尝试使用JSON在适用于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%,主要为17.1%。

如果括号匹配,则肯定有更好的方式返回括号的术语,如果括号匹配?

我简要介绍了Attoparsec-Conduit,但我不知道如何使用该库,甚至无法判断它是否是它可以使用的东西。

编辑:更新了代码。数据来自OpenLibrary.org,E。G。 http://openlibrary.org/data/Ol_dump_authors_latest.txt.gz

有帮助吗?

解决方案

使用scan函数。它允许您扫描维护状态的字符串。在您的情况下,该州将是一个数字 - 到目前为止遇到的开放和关闭括号的差异。 当您的状态为0时,这意味着括号匹配在当前的子字符串内。

诀窍是你没有以这种方式解构和重建字符串,所以它应该更快。

此外,即使通过使用惰性文本使用当前算法,您还可以获得一些性能 - concat功能将更有效地工作。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top