有效地替换二进制对象的一部分

时间:2018-04-25 07:53:45

标签: haskell

我的目标是有效地覆盖blob的几个部分,同时保留其整体内容 和结构原始。为此,我写了以下函数:

replace :: ByteString -> Int -> ByteString -> ByteString
replace source offset replacement = prefix <> replacement <> suffix
  where
    prefix = ByteString.take offset source 
    suffix = ByteString.drop (offset + ByteString.length replacement) source

fix :: Int -> ByteString -> ByteString -> ByteString
fix offset replacement source = replace source offset replacement

这就是他们的工作方式:

λ replace "I have a cat." 0x09 "dog"
"I have a dog."
λ fix 0x0A "fat" . fix 0x03 "dog" $ "My cat is red."
"My dog is fat."

不幸的是,<> = append是线性时间,因此也是这些函数。有了 知道更换只要更换部分,我们当然可以做到 更好?

如果碰巧我们可以及时替换多个部分而不是替换数量的线性,我会特别高兴。

1 个答案:

答案 0 :(得分:2)

鉴于concat在列表大小上是线性的,takedrop都是O(1),这可能与它一样好:

replace source offset replacement = 
  concat [ take offset source
         , replacement
         , drop n source
         ] 
  where n = offset + length replacement

对于任意数量的替换:

replacemany :: [(Int, ByteString)] -> ByteString -> ByteString
replacemany wss bs = foldr f bs wss where
  f (l, ws) bs = replace bs l ws