4

我正在处理一串字节(可以在 10kb 到 3MB 之间的任何位置),我需要过滤掉大约 16 个字节(用其他字节替换它们)

目前我有一个有点像这样的功能..

BYTE_REPLACE = {
  52: 7, # first number is the byte I want to replace
  53: 12, # while the second number is the byte I want to replace it WITH
}
def filter(st):
  for b in BYTE_REPLACE:
    st = st.replace(chr(b),chr(BYTE_REPLACE[b]))
  return st

(为了这个问题,解释了字节列表)

使用 map 导致执行时间约为 0.33 秒,而这导致时间快了 10 倍,约为 0.03 秒(两者都在 HUGE 字符串上执行,压缩后大于 1.5MB)。

虽然任何性能提升都可以忽略不计,但有没有更好的方法来做到这一点?

(我知道存储过滤后的字符串会更加优化。不过,这不是一个选项。我在玩 Minecraft Classic 服务器的关卡格式,并且必须过滤掉某些客户端不支持的字节)

4

3 回答 3

7

使用str.translate

Python 3.x

def subs(st):
    return st.translate(BYTE_REPLACE)

示例用法:

>>> subs('4567')
'\x07\x0c67'

Python 2.x

str.translate(Python 2)

import string
k, v = zip(*BYTE_REPLACE.iteritems())
k, v = ''.join(map(chr, k)), ''.join(map(chr, v))
tbl = string.maketrans(k, v)
def subs(st):
    return st.translate(tbl)
于 2013-09-17T03:33:06.967 回答
4

translate()在字符串上查找方法。这使您可以一次通过字符串进行任意数量的 1 字节转换。使用该string.maketrans()函数构建转换表。如果您通常有 16 对,这应该比执行 16 次 1 字节替换快 16 倍。

于 2013-09-17T03:30:13.200 回答
0

在您当前的设计中,每对都String.replace()在字符串时间上被调用。n虽然它最有可能是一种有效的算法,但在 3MB 的字符串上它可能会变慢。

如果在调用此函数时字符串已经包含在内存中,我敢打赌最有效的方法是:

BYTE_REPLACE = {
  52: 7, # first number is the byte I want to replace
  53: 12, # while the second number is the byte I want to replace it WITH
}
def filter(st):
  st = list(st) # Convert string to list to edit in place :/
  for i,s in enumerate(st): #iterate through list
    if ord(s) in BYTE_REPLACE.keys():
        s[i]=chr(BYTE_REPLACE[ord(b)])
  return "".join(st) #return string

在开始时创建一个新列表有一个很大的操作,另一个是转换回字符串,但由于 Python 字符串在您的设计中是不可变的,因此每次替换都会创建一个新字符串。

这一切都是基于猜想,可能是错误的。你想用你的实际数据来测试它。

于 2013-09-17T03:29:18.793 回答