我的目标是有效地覆盖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
是线性时间,因此也是这些函数。有了
知道更换只要更换部分,我们当然可以做到
更好?
如果碰巧我们可以及时替换多个部分而不是替换数量的线性,我会特别高兴。
答案 0 :(得分:2)
鉴于concat
在列表大小上是线性的,take
和drop
都是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