2017-11-13 3 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 년대에 패턴 일치 할 수 없습니다입니다. 또 다른 옵션은 BS.split이고 Word8 쉼표로 결합하지만 느리고 우아하지 않습니다. 어떤 아이디어?

+1

'Data.ByteString.Char8'을 사용하여 불쾌한'Word8','Char' 변환 및 뒤로 제거하십시오. [Data.ByteString.Char8 첫 번째 문장] (https://hackage.haskell.org/package/bytestring-0.10.8.2/docs/Data-ByteString-Char8.html)에 따라 성능을 변경해서는 안됩니다. 그렇지 않으면'BS.split'은 정말로 도움이되지 않습니다, 당신은 또한'\ n \ r' 조합을 repace하고 싶습니까? 'BS.span (/ = '\ n')'을 사용하여 재귀 함수를 수행 할 것입니다. 우아하지 않지만 잘하면 느린. – Krom

+0

고마워, 그거야! 대답으로 쓰면 – jorgen

+0

Gotcha를 수락합니다. 이전 설명을 편집 할 수 없으므로 여기에 넣기가 너무 혼란스럽지 않기를 바랍니다. @krom – jorgen

답변

1

그래야 할 Word8, Char 개의 전환을 제거하려면 Data.ByteString.Char8을 사용하십시오. Data.ByteString.Char8 first sentence에 따르면 성능을 변경해서는 안됩니다.

또한 \n\r 조합을 바꿀뿐만 아니라 \n도 바꿀 수 있으므로 B.split 대신 B.span을 사용하십시오.

그렇게 할 내 자신의 (아마도 서투른) 시도 :

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.Buildermappendmappend 이미 피연산자 중 하나에 사용 된 횟수에 선형되지, 그렇지 않으면,이 것 여기에 이차 애널로그를 써라.

관련 문제