Skip to main content
 首页 » 编程设计

python之连接和存储长位串的最有效方法是什么

2025年05月04日11mfrbuaa

我正在处理一个数据集,其中包含数万个可变长度的位串,最长可达 32768。

数据源自一个列表,然后我将其连接成多个二进制位串,这些位串又被转换成一个 INT。

演示我的方法:

import array 
 
a = array.array('B', [4,5,13,4,4,9,12,13]) 
d = dict() 
 
for i in set(a): 
    d[i] = int('0b' + ''.join([str(int(i is b)) for b in a]), 2) 
 
print d 

我的问题是:是否有更有效的方法来完成此操作,而无需构造 ~32000 长度的字符串,然后添加“0b”以将其转换为 INT? (我假设除了操作的源列表之外,我的方法至少使用了 32000 字节)

此外,如果我希望以允许按位运算的形式存储它们,那么 INT 是不是最便宜的存储方式?

请您参考如下方法:

如果您需要最大效率,一个应该让您非常接近的包是 bitarray .它是用 C 语言编写的,所以速度快如闪电。

要创建bitarray,您可以向bitarray 构造函数传递任何类似 bool 值的序列。例如:

>>> bitarray.bitarray([1, 1, 0, 1]) 
bitarray('1101') 
>>> bitarray.bitarray([True, True, False, True]) 
bitarray('1101') 
>>> bitarray.bitarray([range(3), [5.829048], [], ['can', 'I', 'help', 'you?']]) 
bitarray('1101') 

我做了一些计时,确实 bitarray 对于较长的字符串来说是最快的。但是有一些惊喜:

    在大多数情况下,
  1. bitarray 仅比 int(''.join(bs)) 快 50%。
  2. int(''.join(bs)) 比 tomasz 提出的 shift 方法更快对于大于 3000 的 a 长度,对于大于 30000 的 a 长度,方式更快。
  3. 即使对于小的 len(a),使用 shift 方法也只是快几倍。 ''.join()对较长字符串提供的渐近性能提升在秒级或几十秒级,而shift方法仅提供级数提升小字符串的毫秒数。因此,使用 ''.join() 显然是赢家。

因此,如果您不想使用外部库,那么像上面那样使用 ''.join() 是最好的解决方案!事实上,在这种情况下使用外部库的好处是微乎其微的;所以最后,我毕竟不会推荐它——除非你主要想节省内存。

最后,一个小提示:您不必像上面那样将'0b' 附加到字符串。只需调用 int(bitstring, 2) —— 基本参数 (2) 使 '0b' 变得多余。

>>> import array 
>>> import random 
>>> import bitarray 
>>>  
>>>        #### Definitions: #### 
>>>  
>>> def a_mask_join(a): 
.....     d = dict() 
.....     for i in set(a): 
.....         d[i] = int(''.join([str(int(i is b)) for b in a]), 2) 
.....     return d 
.....  
>>> def mask(values, x): 
.....     m = 0 
.....     for v in values: 
.....         m = (m << 1) + (v == x) 
.....     return m 
.....  
>>> def a_mask_shift(a): 
.....     d = dict() 
.....     for i in set(a): 
.....         d[i] = mask(a, i) 
.....     return d 
.....  
>>> def a_mask_bitarray1(a): 
.....     d = dict() 
.....     for i in set(a): 
.....         d[i] = bitarray.bitarray([int(i is b) for b in a]) 
.....     return d 
.....  
>>> def a_mask_bitarray2(a): 
.....     d = dict() 
.....     for i in set(a): 
.....         d[i] = int(bitarray.bitarray([int(i is b) for b in a]).to01(), 2) 
.....     return d 
.....  
>>> a = array.array('B', [4,5,13,4,4,9,12,13]) 
>>>  
>>>        #### Test: #### 
>>>  
>>> dicts = (f(a) for f in (a_mask_join, a_mask_shift1, a_mask_shift2, a_mask_bitarray2)) 
>>> sorted_results = (sorted(int(v) for v in d.values()) for d in dicts) 
>>> all(r == sorted(a_mask1(a).values()) for r in sorted_results) 
True 
>>>  
>>>        #### Timing: #### 
>>>  
>>> for size in (int(10 ** (e / 2.0)) for e in range(2, 11)): 
.....     print size 
.....     a = array.array('B', [random.randrange(0, 30) for _ in range(size)]) 
.....     %timeit a_mask_join(a) 
.....     %timeit a_mask_shift(a) 
.....     %timeit a_mask_bitarray1(a) 
.....     %timeit a_mask_bitarray2(a) 
.....  
10 
10000 loops, best of 3: 61.2 us per loop 
100000 loops, best of 3: 17.5 us per loop 
10000 loops, best of 3: 38.4 us per loop 
10000 loops, best of 3: 46.7 us per loop 
31 
1000 loops, best of 3: 343 us per loop 
10000 loops, best of 3: 97.9 us per loop 
1000 loops, best of 3: 212 us per loop 
1000 loops, best of 3: 242 us per loop 
100 
1000 loops, best of 3: 1.45 ms per loop 
1000 loops, best of 3: 486 us per loop 
1000 loops, best of 3: 825 us per loop 
1000 loops, best of 3: 870 us per loop 
316 
100 loops, best of 3: 4.53 ms per loop 
100 loops, best of 3: 2.46 ms per loop 
100 loops, best of 3: 2.53 ms per loop 
100 loops, best of 3: 2.65 ms per loop 
1000 
100 loops, best of 3: 14.5 ms per loop 
100 loops, best of 3: 10.8 ms per loop 
100 loops, best of 3: 7.78 ms per loop 
100 loops, best of 3: 8.04 ms per loop 
3162 
10 loops, best of 3: 47.4 ms per loop 
10 loops, best of 3: 71.8 ms per loop 
10 loops, best of 3: 24.1 ms per loop 
10 loops, best of 3: 25.6 ms per loop 
10000 
10 loops, best of 3: 137 ms per loop 
1 loops, best of 3: 425 ms per loop 
10 loops, best of 3: 75.7 ms per loop 
10 loops, best of 3: 78 ms per loop 
31622 
1 loops, best of 3: 430 ms per loop 
1 loops, best of 3: 3.25 s per loop 
1 loops, best of 3: 241 ms per loop 
1 loops, best of 3: 246 ms per loop 
100000 
1 loops, best of 3: 1.37 s per loop 
1 loops, best of 3: 29.7 s per loop 
1 loops, best of 3: 805 ms per loop 
1 loops, best of 3: 800 ms per loop