我的问题是在列表中找到连续的" 3"。例如list('133233313333')
。使它变得困难的原因只有两个相邻的" 3"是有效的,而三个或更多相邻的" 3"不是。因此," 33"是有效的,但是三重" 3和3333"是无效的。我首先尝试了以下内容:
try:
if l[i] == '3' and l[i+1] == '3' and l[i+2] != '3' and l[i-1] != '3':
record_current(i)
except IndexError:
pass
我的目的是忽略比较,如果有索引,那就不正确,但行不通。
如果列表具有类似dict.get()的方法,返回没有的是keyError,我可以将其写为 (l[i+2] == None or l[i+2] != '3')
。
如果我现在必须完成它,我将从其他项目中静止地对待第一项和最后两个项目。但是,有什么方法可以优雅地解决这个问题吗?
您可以使用itertools.groupby
:
>>> from operator import itemgetter
>>> from itertools import groupby
>>> s = list('1332333133334433')
>>> for k, g in groupby(enumerate(s), itemgetter(1)):
if k == '3':
ind = next(g)[0]
if sum(1 for _ in g) == 1:
print ind
...
1
14
计数连续的3s!
每次遇到" 3"并在非-'3'上重置的计数器会增加一个计数器;比较重置之前的2:
j= 0
for i in range(len(L)):
if L[i] == '3':
j+= 1
else:
if j == 2:
print "Found at", i - j
j= 0
if j == 2:
print "Found at", i - j + 1 # Late fix (+ 1)
另外,人们可能会发现" 3和非-'3的连续运行"。这样,一个人避免在每个非-'3'元素上测试j == 2
,以3序列的每个序列进行一次额外的循环测试:
i= 0
while i < len(L):
# Find the next '3'
while i < len(L) and L[i] != '3':
i+= 1
j= i
# Find the next non-'3'
while i < len(L) and L[i] == '3':
i+= 1
if i - j == 2:
print "Found at", j
您正在尝试检查某个语法。为此,您可以实现确定性的有限自动机(或DFA)。
这是一种使用正则表达式的解决方案:
import re
m = re.finditer('(?<!3)3{2}(?!3)', '1332333133334433')
for x in m:
print x.span()[0]
正则表达式可以找到两个连续三连胜的所有匹配,只要没有后面或先于3。输出为:
1
14
您可以在正则表达式中代替任何字符代替" 3",而是搜索该字母。
data = "1332333133334433"
from itertools import groupby
from operator import itemgetter
result = []
for char, grp in groupby(enumerate(data), itemgetter(1)):
groups = list(grp)
if char == "3" and len(groups) == 2:
result.append(groups[0][0])
print result
输出
[1, 14]
这将返回 True
,如果列表中的'333'
>>> l = "1332333133334433"
>>> any([(i[:3]=='333' and i[3] != '3') for i in map("".join,zip(l[:],l[1:],l[2:],l[3:]))])
True
您可以看到:
>>> map("".join,zip(l[:],l[1:],l[2:],l[3:]))
['1332', '3323', '3233', '2333', '3331', '3313', '3133', '1333', '3333', '3334', '3344', '3443', '4433']
这是找到两个连续的字母的一般解决方案:
def find_two_consecutive(my_str):
prev_letter = None
count = 1
for index, current_letter in enumerate(my_str):
if current_letter == prev_letter:
count += 1
else:
if count == 2:
print("Starting at index: %d" % (index - 2))
count = 1
prev_letter = current_letter
if count == 2:
print("Starting at index: %d" % (index - 2))
如果您的列表实际上只包含一个字母的元素,则应使用re
模块:
import re
chars = list('133233313333433')
numberstr = ''.join(chars)
for match in re.finditer('(?<!3)33(?!3)', numberstr):
print(match.start())
结果:
1
13
模式 (?<!3)33(?!3)
的意思是:找到两个连续的3s,既不是先于也不是3。
可以在此处找到文档。
哦,这是:
chars = list('133233313333433')
numberstr = ''.join(chars)
可能只是:
numberstr = '133233313333433'