You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过从Redis获取的bytearray从ndarray中选取行?

从Redis位串提取索引,选取NumPy数组对应行

我来帮你搞定这个用Redis存储的位集合从NumPy数组里挑对应行的需求!先理清楚你的场景:你通过Redis的setsetbit操作生成了一个位串,拿到的原始字节是b'\xc0\x08',转换成二进制后是0b1100000000001000——也就是第0、1、12位被置为1,目标是从NumPy数组中提取这些索引对应的元素,最终得到array([0, 1, 12])

下面给你两种可行的解决方案,其中@paul-panzer的方案在性能上更优:

方案1:Python字符串+列表推导手动解析

这种方法比较直观,先把字节转换成二进制字符串,再遍历找出所有为1的位索引:

import numpy as np
a_raw = b'\xc0\x08'

# 将字节转换为整数,再转为二进制字符串,补前导零保证位长度准确
bit_str = bin(int.from_bytes(a_raw, byteorder='big'))[2:].zfill(len(a_raw)*8)
# 筛选出所有值为'1'的位索引
indices = np.array([i for i, bit in enumerate(bit_str) if bit == '1'])

# 测试数组(注意要包含索引12,所以数组长度设为13)
arr = np.arange(13)
result = arr[indices]
print(result)  # 输出:array([ 0,  1, 12])

方案2:@paul-panzer的NumPy高效方案

利用NumPy的内置函数直接处理字节数据,避免Python层面的循环操作,速度会快很多:

import numpy as np
a_raw = b'\xc0\x08'

# 将字节转为uint8数组,再解包为比特序列(big字节序)
bits = np.unpackbits(np.frombuffer(a_raw, dtype=np.uint8), bitorder='big')
# 找出所有值为1的位索引
indices = np.where(bits)[0]

arr = np.arange(13)
result = arr[indices]
print(result)  # 输出:array([ 0,  1, 12])

性能对比测试

为了直观展示两种方案的速度差异,我们可以用timeit做基准测试:

import timeit

setup = '''
import numpy as np
a_raw = b'\\xc0\\x08'
'''

# 测试方案1的耗时
t1 = timeit.timeit('''
bit_str = bin(int.from_bytes(a_raw, byteorder='big'))[2:].zfill(len(a_raw)*8)
indices = np.array([i for i, bit in enumerate(bit_str) if bit == '1'])
''', setup=setup, number=100000)

# 测试方案2的耗时
t2 = timeit.timeit('''
bits = np.unpackbits(np.frombuffer(a_raw, dtype=np.uint8), bitorder='big')
indices = np.where(bits)[0]
''', setup=setup, number=100000)

print(f"方案1耗时: {t1:.4f}秒")
print(f"方案2耗时: {t2:.4f}秒")

测试结果通常会显示方案2的耗时远低于方案1,这是因为NumPy的unpackbitswhere都是基于C实现的底层操作,比Python层面的字符串遍历和列表推导高效得多,尤其在处理大量位数据时优势会更明显。

内容的提问来源于stack exchange,提问作者Jacob Eggers

火山引擎 最新活动