Python: list method, similar to dict.get ()

My problem is to find the serial '3 in the list. For example list('133233313333'). What interferes, only two adjacent "3 are valid, three or more adjacent" 3 are not. Thus, “33” is valid, but three times “3” and “3333” are invalid. First I tried the following:

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

My intention is to ignore the comparison and let it be true if there is an IndexError, but it does not work.

If there is a method in the list, for example dict.get () that returns None, there is a KeyError, I could write it as (l[i+2] == None or l[i+2] != '3').

If I have to finish this now, I will process the first element and the last two elements from the other elements. But is there a way to solve this problem elegantly?

+4
source share
8 answers

You can do this using 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
+5
source

Count consecutive 3s!

Keep a counter that increments every time you meet "3" and reset to non-3; compare from 2 to reset:

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)

Alternatively, sequential runs of "3 and non-3" can be found. Thus, one avoids testing j == 2for each element other than '3', due to one additional loop test for each sequence of 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
+1
source

. ( DFA).

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

, :

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

, 3. :

1
14 

"3" , .

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]
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) : 3s, 3.

.

, :

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

:

numberstr = '133233313333433'
0

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']
0

All Articles