我想在一个字节字符串中连接一个整数序列和一个标记列表,例如,以下内容:
foo
bar
baz
将成为(整数表示为1个字节):
b'\x00foo'
b'\x01bar'
b'\x02baz'
我想出的最好看起来像这样:
for i, token in zip(range(256), "foo bar baz".split()):
print(i.to_bytes(1, sys.byteorder) + token.encode())
然而,迭代本身涉及Python的整数和循环中每一步的字节之间的转换,因此它比简单迭代整数要慢得多(对我来说是10倍)。
问题是:有没有办法直接遍历整数的字节字符串表示,而不是整数本身?
答案 0 :(得分:2)
您可以使用numpy直接访问缓冲区接口以避免转换:
在python 2.7(numpy 1.7.1)上,这段代码:
N = arange(256, dtype='uint8')
for i, token in enumerate("foo bar baz".split()):
print repr(N.data[i] + token.encode())
给出:
'\x00foo'
'\x01bar'
'\x02baz'
答案 1 :(得分:1)
我认为可能会更快:
from struct import pack
for i, token in enumerate(b"foo bar bazq".split()):
print(pack('@B%ds' % len(token), i, token))
输出:
b'\x00foo'
b'\x01bar'
b'\x02bazq'
如果您只拥有或想要3个字符串,则可以使用更简单的print
函数/语句:
print(pack('@B3s', i, token))
答案 2 :(得分:1)
如果是固定宽度的令牌(比如3个字符),可以使用numpy记录数组。
如果您的目的不仅是打印数据,而是以某种方便的形式存储数据,具有特定的位顺序,这将非常方便。当然,元素/记录的数量越长,这种方法的效率就越高。
在以下示例中,字符串长度固定为3:
# Create a record array
x = np.zeros((3,),dtype=('u1,a3'))
# Fill the array
x[:] = [(n,s) for n, s in zip(arange(256, dtype='u1'), 'foo bar bax'.split())]
输出:
array([(0, 'foo'), (1, 'bar'), (2, 'bax')],
dtype=[('f0', 'u1'), ('f1', 'S3')])
现在您可以使用所有numpy函数来处理数据。例如,您可以使用:
获取数字字段的数组(字段0,默认情况下命名为'f0')x['f0']
和字符串字段:
x['f1']
这些是原始数组的“视图”,不会使用更多内存。有关numpy记录数组的更多信息可以在numpy docs上找到。
NB:据我所知,这种方法应该适用于python 2.x和3.x。