मुझे एक ऐसा फ़ंक्शन चाहिए जो बाइटस्ट्रिंग लेता है और न्यूलाइन \n और \n\r को अल्पविराम से बदल देता है, लेकिन इसे करने का एक अच्छा तरीका नहीं सोच सकता।

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 अल्पविराम से जुड़ें, लेकिन यह धीमा और सुरुचिपूर्ण लगता है। कोई विचार?

5
jorgen 13 नवम्बर 2017, 16:19

1 उत्तर

सबसे बढ़िया उत्तर

खराब Word8, Char रूपांतरणों से छुटकारा पाने के लिए Data.ByteString.Char8 का उपयोग करें जो आपको अन्यथा करना होगा। Data.ByteString.Char8 प्रथम वाक्य के अनुसार< /a> प्रदर्शन में बदलाव नहीं किया जाना चाहिए।

इसके अतिरिक्त B.split के बजाय B.span का उपयोग करें क्योंकि आप \n\r संयोजनों को भी बदलना चाहते हैं और न केवल \n

मेरा अपना (शायद अनाड़ी) ऐसा करने का प्रयास:

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

उम्मीद है कि mappend Data.ByteString.Builder के लिए रैखिक नहीं है mappend पहले से ही इसके एक ऑपरेंड के लिए उपयोग किया गया था, अन्यथा, यहां एक द्विघात एल्गोरिथम होगा।

2
typetetris 14 नवम्बर 2017, 12:32