Python:寻找含NaN列表中相邻重复值的起始索引(无for循环)
不使用for循环找出列表中相邻重复值的起始索引
给定输入列表 [NaN, NaN, 1, 2, NaN, 2, 2, 2, 4],我们需要找出每组相邻重复值的起始索引,期望输出为 [0, 2, 3, 4, 5, 8]。你已经用for循环实现了正确逻辑,下面提供一种基于numpy向量化操作的无显式循环方案:
无循环实现代码
import numpy as np input_list = [np.nan, np.nan, 1, 2, np.nan, 2, 2, 2, 4] arr = np.array(input_list) # 生成相邻元素是否属于不同组的布尔数组,单独处理NaN的特殊情况 # 由于NaN与自身比较结果为False,需额外判断相邻是否均为NaN not_same_group = np.logical_or( arr[1:] != arr[:-1], np.logical_and(np.isnan(arr[1:]), np.isnan(arr[:-1])) ) # 第一个元素必然是一组的起始,在布尔数组开头补True mask = np.concatenate([[True], not_same_group]) # 提取所有标记为起始位置的索引 start_adj_i = np.where(mask)[0].tolist() print(start_adj_i) # 输出: [0, 2, 3, 4, 5, 8]
代码说明
- 将输入列表转为numpy数组,利用向量化运算替代显式循环
not_same_group数组标记从第二个元素开始,当前元素与前一个是否属于不同重复组:- 非NaN值直接通过
arr[1:] != arr[:-1]判断 - NaN需额外判断相邻是否均为NaN,这种情况属于同一组,不标记为不同
- 非NaN值直接通过
- 在数组开头补
True,因为第一个元素肯定是一组的起始 - 用
np.where提取所有起始位置的索引,转成列表即为结果
原循环实现对比
你原有的for循环逻辑正确,核心是跟踪前一个值,判断当前值是否属于新的重复组:
import numpy as np start_adj_i = [] prev_val = -999 # 一个不可能出现在列表中的值 for i, x in enumerate(input_list): if np.isnan(x) and np.isnan(prev_val): continue elif x != prev_val: start_adj_i.append(i) prev_val = x # 更新前一个值用于下一次迭代 print(start_adj_i) # 输出: [0, 2, 3, 4, 5, 8]
内容的提问来源于stack exchange,提问作者nk123
相关产品推荐
相关产品推荐

