
本文介绍一种仅用三行NumPy代码,将升序变化索引数组(如 [2, 5, 9, 10])转换为对应长度的交替二进制数组(如 [0,0,1,1,1,0,0,0,0,1,0])的方法,核心利用布尔累积和模2运算实现状态翻转。
本文介绍一种仅用三行numpy代码,将升序变化索引数组(如 `[2, 5, 9, 10]`)转换为对应长度的交替二进制数组(如 `[0,0,1,1,1,0,0,0,0,1,0]`)的方法,核心利用布尔累积和模2运算实现状态翻转。
要生成一个在指定索引处“翻转”值(0↔1)的二进制数组,关键在于将离散的切换点转化为连续的状态序列。NumPy 提供了一种简洁而高效的向量化方案,无需循环或分段拼接:
import numpy as np a = np.array([2, 5, 9, 10]) x = np.zeros(a.max() + 1, dtype=np.uint8) # 初始化全0数组,长度覆盖最大索引+1 x[a] = 1 # 在切换位置置1 → [0,0,1,0,0,1,0,0,0,1,1] b = x.cumsum() % 2 # 累积和后取模2 → [0,0,1,1,1,0,0,0,0,1,0]
该方法的逻辑清晰:
-
x[a] = 1在每个变化点标记一次“触发事件”; -
cumsum()将这些事件转化为递增计数器(每遇到一个1就加1),从而隐式记录已发生的翻转次数; -
% 2将奇偶性映射为1/0,自然形成交替模式。
⚠️ 注意事项:
- 输入数组
a必须严格升序且非负(NumPy索引要求); - 若
a为空,需单独处理(例如b = np.array([0])或根据初始值约定); - 使用
np.uint8可节省内存,但因cumsum % 2仅依赖奇偶性,即使发生整数溢出(如uint8溢出回绕),结果依然正确——这是该技巧鲁棒性的关键; - 若首段应以
1开始,只需将最终结果取反:b = 1 - (x.cumsum() % 2)。
此方案时间复杂度为 O(n),空间复杂度为 O(max(a)),完全向量化,适用于中等规模索引(百万级以内)。对于超大规模稀疏切换场景,可考虑 scipy.sparse 或分段生成策略,但对绝大多数实际需求,上述三行代码已是优雅而高效的“NumPy 魔法”。










