在字节表示中有效地增加整数序列

时间:2013-07-05 17:12:11

标签: python python-3.x

我想在一个字节字符串中连接一个整数序列和一个标记列表,例如,以下内容:

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倍)。

问题是:有没有办法直接遍历整数的字节字符串表示,而不是整数本身?

3 个答案:

答案 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。