2017-11-13 11 views
3

ByteStringを使用し、改行を\n\n\rに置き換えますが、それを行うには良い方法は考えられません。ByteStringの改行を置き換えます。

import qualified Data.ByteString as BS 
import Data.Char (ord) 
import Data.Word (Word8) 

endlWord8 = fromIntegral $ ord '\n' :: Word8 

replace :: BS.ByteString -> BS.ByteString 

私はBS.mapを使用するのではと思ったが、どのように私はWord8年代のパターンと一致することはできませんので、見ることができません。もう1つのオプションはBS.splitで、次にWord8コンマで結合しますが、遅くて控えめに聞こえます。何か案は?

+1

'Data.ByteString.Char8'を使用して、厄介な' Word8'、 'Char'変換を取り除いて戻します。 [Data.ByteString.Char8 first sentence](https://hackage.haskell.org/package/bytestring-0.10.8.2/docs/Data-ByteString-Char8.html)に従ってパフォーマンスを変更しないでください。それ以外の場合、 'BS.split'は本当に助けにはなりません。あなたは' \ n \ r'の組み合わせにも反復したいのですか? 'BS.span(/ = '\ n')'で再帰関数を実行します。控えめではあるが、うまくいけばスローが遅くない。 – Krom

+0

ありがとう、それは動作します!あなたが答えとしてそれを書くなら、私は – jorgen

+0

Gotchaを受け入れます。私は前のコメントを編集することができないので、ここでそれを置くのがあまりにも混乱しないことを願っています:@krom – jorgen

答えて

1

Data.ByteString.Char8を使用すると、そうしなければならない厄介なWord8,Charのコンバージョンを取り除くことができます。 Data.ByteString.Char8 first sentenceによると、パフォーマンスを変更しないでください。あなたも\n\rの組み合わせだけでなく\nを交換したいと

さらにB.spanの代わりB.splitを使用しています。

これを行うには私自身の(たぶん不器用)の試行:

module Test where 

import Data.Monoid ((<>)) 
import Data.ByteString.Char8 (ByteString) 
import qualified Data.ByteString.Char8 as B 
import qualified Data.ByteString.Builder as Build 
import qualified Data.ByteString.Lazy as LB 

eatNewline :: ByteString -> (Maybe Char, ByteString) 
eatNewline string 
    | B.null string = (Nothing, string) 
    | B.head string == '\n' && B.null (B.tail string) = (Just ',', B.empty) 
    | B.head string == '\n' && B.head (B.tail string) /= '\r' = (Just ',', B.drop 1 string) 
    | B.head string == '\n' && B.head (B.tail string) == '\r' = (Just ',', B.drop 2 string) 
    | otherwise = (Nothing, string) 

replaceNewlines :: ByteString -> ByteString 
replaceNewlines = LB.toStrict . Build.toLazyByteString . go mempty 
    where 
    go :: Build.Builder -> ByteString -> Build.Builder 
    go builder string = let (chunk, rest) = B.span (/= '\n') string 
          (c, rest1) = eatNewline rest 
          maybeComma = maybe mempty Build.char8 c 
         in if B.null rest1 then 
          builder <> Build.byteString chunk <> maybeComma 
          else 
          go (builder <> Build.byteString chunk <> maybeComma) rest1 

をうまくいけば、Data.ByteString.Builderためmappendmappendはすでにそのオペランドの1のために使用された回数に直線的ではない、そうでない場合は、そこだろうここでは二次的な推論です。

関連する問題