Python:list的方法类似于dict.get()



我的问题是在列表中找到连续的" 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'

最新更新