从列表末尾删除连续的事件
我有一个numpy数组:
ar = np.array([True, False, True, True, True])
如果最后一个元素为True,我想删除数组末尾的所有连续true元素。 举个例子
magic_func(ar) => [True, False]
如果ar = [True, False, True, False, True]
。 然后
magic_func(ar) => [True, False, True, False]
如果ar = [True, False, False]
,则该函数不执行任何操作,因为最后一个元素为False
Python中是否有一行代码需要执行此操作? 使用一个numpy库或其他东西
这一行功能应该可以工作,但看起来非常讨厌,可能效率不高。 基本上这个想法是找到最正确的False
并在False
之前返回所有的值
def magic_func(a):
return a[:len(a)-np.where(a[::-1]==False)[0][0]] if np.where(a[::-1]==False)[0].size>0 else a[:0]
>>> a = np.array([False, True, True, True, True])
>>> magic_func(a)
array([False], dtype=bool)
像这样使用itertools.dropwhile
和np.fromiter
。
from itertools import dropwhile
np.fromiter(dropwhile(lambda x: x, ar[::-1]), dtype=bool)[::-1]
编辑
这是更快的方法(只需使用itertools.takewhile
)
from itertools import takewhile
ar[:-sum(1 for i in takewhile(lambda x: x, reversed(ar)))]
时间:
ar = np.array([True, False, True, True, True])
#mine
%timeit ar[:-sum(1 for i in takewhile(lambda x: x, reversed(ar)))]
1000000 loops, best of 3: 1.84 us per loop
#mine
%timeit np.fromiter(dropwhile(lambda x: x, ar[::-1]), dtype=bool)[::-1]
100000 loops, best of 3: 2.93 us per loop
#@Jaime
%timeit ar[np.bitwise_or.accumulate(~ar[::-1])[::-1]]
100000 loops, best of 3: 3.63 us per loop
#@askewchan
%timeit ar[:len(ar)-np.argmin(ar[::-1])]
100000 loops, best of 3: 6.24 us per loop
#@xbb
%timeit ar[:len(ar)-np.where(ar[::-1]==False)[0][0]] if np.where(ar[::-1]==False)[0].size>0 else ar[:0]
100000 loops, best of 3: 7.61 us per loop
PS:
这是没有魔法的功能。
def no_magic_func(ar):
for i in xrange(ar.size-1, -1, -1):
if not ar[i]:
return ar[:i+1]
return ar[0:0]
时间:
ar = np.array([True, False, True, True, True])
%timeit no_magic_func(ar)
1000000 loops, best of 3: 954 ns per loop
这对我的喜好来说有点太神奇了,但它看起来确实很好:
>>> ar = np.array([True, False, True, True, True])
>>> ar[np.bitwise_or.accumulate(~ar[::-1])[::-1]]
array([ True, False], dtype=bool)
为了理解正在发生的事情,首先我们否定数组,将True
变成False
,反之颠倒顺序,然后我们累加OR数组的结果:这将是False
直到第一个True
,并且此后将保持为True
。 颠倒这个数组,我们有一个布尔索引数组,它将摆脱所有尾随True
。
上一篇: Removing consecutive occurrences from end of list python