如何用Pythonic风格及Numpy简化数组区间条件索引查找并解决np.argwhere报错
嘿,我来帮你搞定这个问题!咱们分两部分来:先把纯Python的代码改成最地道的Pythonic风格,再解决NumPy里的报错问题。
一、纯Python的Pythonic简化实现
你的原代码用了显式循环和列表追加,其实用列表推导式就能一行搞定,这也是Python里最简洁且符合风格的写法:
myList = [4.2, 6.0, 10.2] low = 10 high = 11 indices = [i for i, v in enumerate(myList) if low < v < high]
运行后indices会得到[2],和原代码结果完全一致,但代码更紧凑易读。
二、NumPy的正确实现 & 报错原因解析
为什么会报错?
你用np.argwhere(low < myList < high)触发报错的核心原因是:Python的链式比较a < b < c会被解释成(a < b) and (b < c),但这个逻辑在NumPy数组上不适用——数组的布尔运算需要用元素级的逻辑与&,而且因为运算符优先级的问题,每个条件必须用括号括起来。
如果直接写low < myList < high,Python会先计算low < myList得到一个布尔数组,然后尝试把这个布尔数组和high(标量)比较,这就会触发ValueError: The truth value of an array with more than one element is ambiguous,因为NumPy不知道你要判断整个数组的真值还是单个元素。
正确的NumPy实现
这里有几种简洁的写法:
方法1:用np.argwhere(修正版)
import numpy as np myArray = np.array([4.2, 6.0, 10.2]) low = 10 high = 11 # 用&连接两个元素级条件,每个条件加括号 indices = np.argwhere((myArray > low) & (myArray < high)).flatten()
np.argwhere会返回二维数组(比如array([[2]])),用flatten()可以把它转成一维数组array([2]),和纯Python的结果格式更匹配。
方法2:用np.where(更直接)
np.where直接返回符合条件的索引的元组,取第一个元素就是一维索引数组:
indices = np.where((myArray > low) & (myArray < high))[0]
方法3:用布尔索引+np.arange
这也是一种很Pythonic的NumPy写法:
# 先生成所有索引,再用布尔条件筛选 indices = np.arange(len(myArray))[(myArray > low) & (myArray < high)]
这三种方法运行后都会得到array([2]),完全符合你的需求。
内容的提问来源于stack exchange,提问作者Julian M

