[英]find if element appears n times in a row in python list
myList = [True, True, False, False, True, False, True, False, False]
I want to find if True appears 3 times in a row. 我想找到True是否连续出现3次。
I can find it by doing: 我可以通过这样做找到它:
for x0, x1, x2 in zip(myList, myList[1:], myList[2:]):
if x0 == True and x1 == True and x2 == True:
print True
Is there a better way? 有没有更好的办法?
Use itertools.groupby()
to group elements, then count each group. 使用itertools.groupby()
对元素进行分组,然后对每个组进行计数。 Using the any()
function lets you exit the loop early if a match was found: 如果找到匹配项,使用any()
函数可以提前退出循环:
from itertools import groupby, islice
print any(sum(1 for _ in islice(g, 3)) == 3 for k, g in groupby(myList) if k)
The if k
filters the groups to only count the groups of True
values. if k
过滤组仅计算True
值组。
The itertools.islice()
function ensures we only look at the first 3 elements of a group, and ignore the rest of that group. itertools.islice()
函数确保我们只查看组的前3个元素,并忽略该组的其余部分。 This way you avoid having to count the next however many True
values just to determine that you found at least 3. 这样你就可以避免计算下一个很多True
值,只是为了确定你找到了至少3个。
Demo: 演示:
>>> from itertools import groupby, islice
>>> myList = [True, True, False, False, True, False, True, False, False]
>>> [sum(1 for _ in islice(g, 3)) for k, g in groupby(myList) if k]
[2, 1, 1]
>>> any(sum(1 for _ in islice(g, 3)) == 3 for k, g in groupby(myList) if k)
False
>>> myList = [True, True, False, False, True, True, True, True, False, True, False, False]
>>> [sum(1 for _ in islice(g, 3)) for k, g in groupby(myList) if k]
[2, 3, 1]
>>> any(sum(1 for _ in islice(g, 3)) == 3 for k, g in groupby(myList) if k)
True
I used a list comprehension to show the group sizes (counting only True
groups) to show why the any()
call returns False
first, then True
; 我使用列表推导来显示组大小(仅计算True
组)以显示为什么any()
调用首先返回False
,然后返回True
; the second example has a group of 4 consecutive True
values. 第二个例子有一组4个连续的True
值。
I like the brevity of the groupby
, but I find the following slightly more readable so I thought I'd add an alternative; 我喜欢groupby
的简洁,但我觉得下面的内容稍微有些可读性,所以我想我会添加一个替代方案;
needle = 3 * [True]
any(1 for i in range(len(myList)) if myList[i:i+len(needle)] == needle)
Here it is my solution 这是我的解决方案
% cat hsol.py
import itertools
myList = [True, True, False, False, True, False, True, False, False]
def test_sequentiality(l, item, n):
if n>len(l): return False
s = 0
for i in l:
if i != item:
s = 0
else:
s = s+1
if s == n: return True
return False
print test_sequentiality(myList, True, 3)
print test_sequentiality(myList, True, 2)
% python2 hsol.py
False
True
%
One way would be to reduce the if statements etc in your question, and directly print the boolean value. 一种方法是减少问题中的if语句等,并直接打印布尔值。
for x0, x1, x2 in zip(myList, myList[1:], myList[2:]):
print x0 == x1 == x2 == True
Using any
statement, we can short circuit the same 使用any
语句,我们都可以短路
any(x0 == x1 == x2 == True for (x0, x1, x2) in zip(myList, myList[1:], myList[2:]))
print reduce(
lambda acc, x: (acc[0]+1 if x else 0, max(acc[0], acc[1])),
myList+[None],
(0, 0)
)[1]
It will accumulate the sequential counts of True
with maximal count of sequential True
s +[None]
is needed in case the longest sequence ends with last element. 如果最长序列以最后一个元素结束,它将累积顺序计数True
,最大计数顺序为True
s +[None]
。
A straightforward and (in my opinion) very easy-to-understand way: 一个直截了当的(在我看来)非常容易理解的方式:
myList = [True, True, False, False, True, False, True, False, False]
v = True # search for this value
n = 3 # number of consecutive appearances of v
vList = [v] * n
for i in range(len(myList) - n):
if myList[i:i + n] == vList:
print True
break
else:
print False
It's kind of C-style (or Pascal or Fortran, etc.), but simple. 它有点C风格(或Pascal或Fortran等),但很简单。 The above code assumes you just want a single True
or False
at the end. 上面的代码假设您最后只需要一个True
或False
。 You can easily adapt it if you want to print the index of each found occurrence. 如果要打印每个找到的事件的索引,可以轻松调整它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.