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

时间:2014-01-21 09:21:48

标签: python algorithm

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

我的意图是忽略比较,如果存在IndexError,它就是真的,但它不起作用。

如果list有一个类似dict.get()的方法,它返回None是一个KeyError,我可以把它写成(l[i+2] == None or l[i+2] != '3')

如果我现在必须完成它,我会从其他项目中特别对待第一项和最后两项。但有没有办法优雅地解决这个问题?

8 个答案:

答案 0 :(得分:5)

您可以使用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

答案 1 :(得分:1)

计算连续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

答案 2 :(得分:0)

您正在尝试检查某个语法。为此,您可以实施Deterministic Finite Automaton(或DFA)。

答案 3 :(得分:0)

这是找到两个相同字母的通用解决方案:

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))

答案 4 :(得分:0)

以下是使用正则表达式的解决方案:

import re
m = re.finditer('(?<!3)3{2}(?!3)', '1332333133334433')
for x in m:
    print x.span()[0]

正则表达式查找两个连续三个棋子的所有匹配项,只要它们不是后跟或前面的3.输出为:

1
14 

您可以在正则表达式中将任何字符替换为“3”,以搜索该字母。

答案 5 :(得分:0)

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]

答案 6 :(得分:0)

如果您的列表实际上只包含一个字母的元素,则应使用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)表示:找到两个连续的3,既不是前面也不后面是3。

可以找到文档here

哦,这个:

chars = list('133233313333433')
numberstr = ''.join(chars)

应该只是:

numberstr = '133233313333433'

答案 7 :(得分:0)

如果列表中的“333”

,则返回True
>>> 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']