计算python列表中标记之间出现的次数

计算python列表中标记之间出现的次数,python,algorithm,numpy,Python,Algorithm,Numpy,我有一个布尔(numpy)数组。我想数一数“真”和“假”之间出现的次数 例如,对于示例列表: b_List = [T,T,T,F,F,F,F,T,T,T,F,F,T,F] 应该产生 ml = [3,3,1] 我最初的尝试是尝试以下代码段: i = 0 ml = [] for el in b_List: if (b_List): i += 1 ml.append(i) i = 0 但是它不断地为b_列表中的每个F追加ml元素 编辑 谢谢大家的回答。遗憾的是,我不能接受所

我有一个布尔(numpy)数组。我想数一数“真”和“假”之间出现的次数

例如,对于示例列表:

b_List = [T,T,T,F,F,F,F,T,T,T,F,F,T,F] 
应该产生

ml = [3,3,1]
我最初的尝试是尝试以下代码段:

i = 0
ml = []
for el in b_List:
  if (b_List):
    i += 1
  ml.append(i)
  i = 0
但是它不断地为b_列表中的每个F追加ml元素

编辑

谢谢大家的回答。遗憾的是,我不能接受所有的答案都是正确的。我接受了阿卡瓦尔的回答,因为他提到了我最初的尝试(我知道我现在做错了什么),并对马克和阿什维尼斯的帖子进行了比较

请不要将公认的解决方案作为定义答案,因为其他两个建议都引入了同样有效的替代方法

提供了一种简单的方法:

>>> import itertools
>>> T, F = True, False
>>> b_List = [T,T,T,F,F,F,F,T,T,T,F,F,T,F]
>>> [len(list(group)) for value, group in itertools.groupby(b_List) if value]
[3, 3, 1]

使用
NumPy

>>> import numpy as np
>>> a = np.array([ True,  True,  True, False, False, False, False,  True,  True, True, False, False,  True, False], dtype=bool)
>>> np.diff(np.insert(np.where(np.diff(a)==1)[0]+1, 0, 0))[::2]
array([3, 3, 1])

>>> a = np.array([True, False, False, True, True, False, False, True, False])
>>> np.diff(np.insert(np.where(np.diff(a)==1)[0]+1, 0, 0))[::2]
array([1, 2, 1])
不能说这是最好的NumPy解决方案,但它仍然比itertools快。groupby:

>>> lis = [ True,  True,  True, False, False, False, False,  True,  True, True, False, False,  True, False]*1000
>>> a = np.array(lis)
>>> %timeit [len(list(group)) for value, group in groupby(lis) if value]
100 loops, best of 3: 9.58 ms per loop
>>> %timeit np.diff(np.insert(np.where(np.diff(a)==1)[0]+1, 0, 0))[::2]
1000 loops, best of 3: 1.4 ms per loop

>>> lis = [ True,  True,  True, False, False, False, False,  True,  True, True, False, False,  True, False]*10000
>>> a = np.array(lis)
>>> %timeit [len(list(group)) for value, group in groupby(lis) if value]
1 loops, best of 3: 95.5 ms per loop
>>> %timeit np.diff(np.insert(np.where(np.diff(a)==1)[0]+1, 0, 0))[::2]
100 loops, best of 3: 14.9 ms per loop
正如@justhalf和@Mark Dickinson在评论中指出的,上述代码在某些情况下不起作用,因此您需要首先在两端追加
False

In [28]: a                                                                                        
Out[28]: 
array([ True,  True,  True, False, False, False, False,  True,  True,
        True, False, False,  True, False], dtype=bool)

In [29]: np.diff(np.where(np.diff(np.hstack([False, a, False])))[0])[::2]
Out[29]: array([3, 3, 1])

您最初的尝试存在一些问题:

i = 0
ml = []
for el in b_List:
    if (b_List): # b_list is a list and will evaluate to True
                 # unless you have an empty list, you want if (el)
        i += 1
    ml.append(i) # even if the above line was correct you still get here
                 # on every iteration, and you don't want that
    i = 0
你可能想要这样的东西:

def count_Trues(b_list):
    i = 0
    ml = []
    prev = False
    for el in b_list:
        if el:
            i += 1
            prev = el
        else:
            if prev is not el:
                ml.append(i)
                i = 0
            prev = el
    if el:
        ml.append(i)
    return m
结果:

>>> T, F = True, False
>>> b_List = [T,T,T,F,F,F,F,T,T,T,F,F,T,F] 
>>> count_Trues(b_List)
[3, 3, 1]
>>> b_List.extend([T,T])
>>> count_Trues(b_List)
[3, 3, 1, 2]
>>> b_List.extend([F])
>>> count_Trues(b_List)
[3, 3, 1, 2]
此解决方案运行速度惊人:

In [5]: T, F = True, False

In [6]: b_List = [T,T,T,F,F,F,F,T,T,T,F,F,T,F] 

In [7]: new_b_List = b_List * 100

In [8]: import numpy as np

# Ashwini Chaudhary's Solution
In [9]: %timeit np.diff(np.insert(np.where(np.diff(new_b_List)==1)[0]+1, 0, 0))[::2]
1000 loops, best of 3: 299 us per loop

In [11]: %timeit count_Trues(new_b_List)
1000 loops, best of 3: 130 us per loop

In [12]: new_b_List = b_List * 1000

# Ashwini Chaudhary's Solution 
In [13]: %timeit np.diff(np.insert(np.where(np.diff(new_b_List)==1)[0]+1, 0, 0))[::2]
100 loops, best of 3: 2.25 ms per loop

In [14]: %timeit count_Trues(new_b_List)
100 loops, best of 3: 1.33 ms per loop

这看起来很接近,但它是否应该排除第一个真值,因为它不是“介于”错误之间?@bcollins:从OP给出的示例来看,这些真值似乎应该包括在内。事实证明,这基本上是Alex Martelli在一个几乎重复的问题上给出的答案的重复。(除了Alex将
len(list(group))
替换为
sum(group)
,这有点整洁。)对于NumPy数组,几乎可以肯定的是,您应该使用Ashwini Chaudhary提供的向量化解决方案。@MarkDickinson我对NumPy非常陌生,所以我相信这可以用更好的方式来实现。如果你找到更好的答案,一定要贴出来。;-)这不可能完全正确
np.diff(a)
将给出相同的数组,如果
True
False
互换,但是答案应该改变(在大多数情况下)@justhalf:Yes;我认为如果序列以一个
False
开头,这就不太管用了。比如:
np.diff(np.where(np.diff(np.insert(a,0,False))==1)[0])[::2]
之类的东西怎么样?不;当末尾出现
True
时,该操作将失败。在我看来,按照这些思路,正确的解决方案似乎是在开始和结束时都加上一个
False
,然后再做第一个
diff
。把你的答案和Alex Martelli关于这个问题的答案混在一起,我建议:
np.diff(np.where)(np.diff(np.hstack([False,a,False]))[0][::2]
为了进行更公平的比较,您可能应该将
new\u b\u List
制作成一个NumPy数组,而不是Python列表。