Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 跳过括号内的术语?_Haskell_Conduit_Attoparsec - Fatal编程技术网

Haskell 跳过括号内的术语?

Haskell 跳过括号内的术语?,haskell,conduit,attoparsec,Haskell,Conduit,Attoparsec,我试图使第5列中包含JSON的大型TSV文件适合导入mongoDB。 特别是,我想将顶级和仅顶级关键字段更改为_id。这是我到目前为止所做的,它似乎可以工作,但速度很慢: {-# LANGUAGE OverloadedStrings #-} import System.Environment (getArgs) import Data.Conduit.Binary (sourceFile, sinkFile) import Data.Conduit import qualified Data.

我试图使第5列中包含JSON的大型TSV文件适合导入mongoDB。 特别是,我想将顶级和仅顶级关键字段更改为_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
{-#语言重载字符串}
导入System.Environment(getArgs)
导入Data.conductor.Binary(sourceFile,sinkFile)
导入数据。管道
将限定的Data.conductor.Text作为CT导入
导入符合条件的数据.conductor.List作为CL
导入符合条件的数据。文本为T
导入数据。Monoid(())
将Data.c.Text作为APT导入
导入控制
main=do
(inputFile:outputFile:uuu)T.Text
jsonify=go。T.splitOn“\T”
哪里
go(:::::::::::::)=大小写解析仅适用于内容的keyTo_id
右res->res“\n”
_ -> ""
go uquo
keyTo_id::解析器T.Text
keyTo_id=skipWhile(/='{')>>T.snoc
(T.cons(char'{'))
(T.concat many1(括号
(字符串“\”key\”:“>>返回“\”\u id\”:”)
APT.takeWhile1(\x->x/='{'&&x/='}'&&x/='''”)
T.singleton满足(/='}')
)))  
字符'}'
括号::解析器T.Text
括号=T.cons字符'{'
扫描1测试
哪里
测试::Int->Char->Maybe Int
测试0=无
测试i'}'=Just(i-1)
测试i'{'=Just(i+1)
测试i=仅测试i
根据探查器,58.7%的时间花在括号内,19.6%花在键盘上,17.1%花在主键盘上

如果括号匹配,肯定有更好的方法返回括号内的术语不变吗

我简单地看了一下ATOPASSEC导管,但我不知道如何使用该库,甚至不知道它是否可以用于这种用途


编辑:更新了代码。数据来自openlibrary.org,例如使用
scan
函数。它允许您扫描一个保持状态的字符串。在您的情况下,状态将是一个数字-到目前为止遇到的大括号的打开和关闭的差异。 当状态为0时,这意味着大括号在当前子字符串中匹配

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


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

我尝试了扫描,它将空间效率提高了约15%,速度提高了约5%。我不确定如何实现您的第二个建议,因为takeWhi似乎没有惰性文本版本le1或conductor.Text函数,因此我似乎必须来回转换几次。