我可以比较一下列表的一部分吗



此代码将选择列表"a"的6个或更多正值

a=np.array([1.01, -1.58, 0.64, 1.38, 0.69, 0.91, 1.34, 1.03, 1.39, 0.94, -1.01,0.16])
b= np.zeros(13)
for i in range(6):
if (a[i] > 0 and a[i+1] > 0 and a[i+2] > 0 and a[i+3] > 0
and a[i+4] > 0 and a[i+5] > 0 and a[i+6] > 0) :

b[i] = a[i]
b[i+1] = a[i+1]
b[i+2] = a[i+2]
b[i+3] = a[i+3]
b[i+4] = a[i+4]
b[i+5] = a[i+5]
b[i+6] = a[i+6]

我想把它缩短,我试过了:

for i in range (6):
if (a[i:i+6]) > 0:
b[i:i+6] = a[i:i+6]

再次访问这个方法-我想添加这个替代方法,其中包括我在以前的回答中提到的优化:

这个版本要长得多,并且需要手工编码每个正数序列的索引跟踪。但它具有主要的性能优势,如下所述。

a = np.array([1.01, -1.58, 0.64, 1.38, 0.69, 0.91, 1.34, 1.03, 1.39, 0.94, -1.01, 0.16,])
b = np.zeros(len(a))
MIN_CONSECUTIVE = 6  # number of consecutive numbers wanted
first, last, c = -1, -1, 0  # index of first & last positive number, count of +ve nums
nums = []  # hold each series of consecutive positive numbers
for i, n in enumerate(a):
if n > 0:
nums.append(n)
first = i if first == -1 else first
last = i
c += 1
else:
if c >= MIN_CONSECUTIVE:
b[first:last+1] = nums
first, last, c = -1, -1, 0  # reset
nums = []  # reset
if i > len(a) - MIN_CONSECUTIVE - 1:  # shortcut exit if there aren't
break                             # enough elems left for consecutive
else:  # if the loop completes without `break`
if c >= MIN_CONSECUTIVE:  # also check after the loop completes
b[first:last+1] = nums
b  # -> array([0.  , 0.  , 0.64, 1.38, 0.69, 0.91, 1.34, 1.03, 1.39, 0.94, 0.  , 0.  ])

为什么这样更好:

  1. 这个访问和访问numpy数组(或python列表(中的每个项目一次
    • 您尝试的方法,在评论和我之前的回答中提供,多次查找数组中重叠的系列元素
    • 前一个也多次重新写入b,并用相同的值重写
  2. 这只会在找到并完成每个系列后写入b
  3. 我正在使用enumerate()跟踪索引,但我不使用索引访问元素。对python列表的索引访问比只遍历列表的元素要慢。numpy数组也是如此
  4. 对于您给定的列表,此列表的运行时间不到上一个答案的一半:
    • 这个:14.6µs±584 ns
    • 上一篇:31.9µs±1.13µs

在缩短的版本中,您需要更改的主要内容是if (a[i:i+6]) > 0:。此外,a的长度是12,b的长度是13。编辑1:(根据@Steve下面的评论(此外,索引range循环也可以从for i in range(6)推广到for i in range(len(a)-5)因此:

b = np.zeros(len(a))
# b is 
# array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
for i in range(len(a)-5):
if all(a[i:i+6] > 0):
b[i:i+6] = a[i:i+6]
b
# output:
# array([0.  , 0.  , 0.64, 1.38, 0.69, 0.91, 1.34, 1.03, 1.39, 0.94, 0.  , 0.  ])

编辑2,根据@hpaulj的评论,由于a是一个numpy数组,我们不需要迭代切片,因为numpy会将>运算符应用于数组(切片(的每个元素,并返回一个[True,False, ...]的数组。第一个循环是这样的:

例如a[0:0+6] > 0返回array([ True, False, True, True, True, True])


一次只检查6个元素的一个显著缺点是,如果是一组更长的连续正数,它将在下一个循环中填充,并重写b中已经存在的相同值。所以不是很优化。最好对索引进行显式检查,直到得到非正(或结束(,并确保您当前处于计数状态>6.

最新更新