Reputation: 43
I'm working on processing words in python and I want to see if a string has 3 or more occurances of the same letter back to back .Is there a better way to do that other than a nested for loop ? example: "helllooooo"
Upvotes: 2
Views: 2079
Reputation: 30032
Idea is to shift
the word and compare,
First, create a Pandas Series from the given word
import pandas as pd
s = pd.Series(list(w))
print(s)
0 h
1 e
2 l
3 l
4 l
5 o
6 o
7 o
8 o
9 o
dtype: object
Then you can group by and shift
the Series to find continuous char
m = s.groupby(s).filter(lambda g: g.eq(g.shift().bfill()).sum() >= 3)
print(m)
2 l
3 l
4 l
5 o
6 o
7 o
8 o
9 o
dtype: object
If you want to determine the repeated char and repeated times
print(m.value_counts())
o 5
l 3
dtype: int64
If you want to find the location of repeated chars
i = m.groupby(m).apply(lambda g: g.iloc[[0, -1]].index.tolist()).to_dict()
print(i)
{'l': [2, 4], 'o': [5, 9]}
Upvotes: 0
Reputation: 77347
There's a tool for that. itertools.groupby
will group by each change in a primary key (in this case, the next letter in the word). Its second term is an iterator that will emit like valued items (consecutive letters).
>>> import itertools
>>> for letter, seq in itertools.groupby("hellloooooooo"):
... sz = len(list(seq))
... if sz >= 3:
... print(letter, sz)
...
l 3
o 8
You could break out of the loop early if you only care about finding the first sequence, as in
for _, seq in itertools.groupby("hellloooooooo"):
if len(list(seq)) >= 3:
has_3 = True
break
else:
has_3 = False
Upvotes: 0
Reputation: 37539
Can be done pretty succinctly with regular expressions
>>> import re
>>> re.findall(r"((?P<s>[a-zA-Z0-9])(?P=s){2,})", "hellllooooooo")
[('llll', 'l'), ('ooooooo', 'o')]
Upvotes: 0
Reputation: 27008
There's probably a better way (there usually is) but if you're looking for any character that repeats at least n times consecutively in a string then:
def has_repeats(s, n=3):
for i in range(len(s)-n+1):
if (a := s[i:i+n]).count(a[0]) == n:
return True
return False
print(has_repeats('helllooooo'))
Output:
True
The default value for n is 3. You could override this if needed to any number.
If you're looking specifically for a sequence of 3 characters then this might be faster:
def has_3_repeats(s):
for t in zip(s, s[1:], s[2:]):
if t.count(t[0]) == 3:
return True
return False
Upvotes: 0
Reputation: 34
here's a function I've made, it should return True
if the word has repeated letters, False
if it doesn't.
def repeated_letters(word:str):
count = 0
for i in range(len(word) -1):
if word[i] == word[i+1]:
count += 1
if count == 2:
return True
else:
count = 0
return False
Upvotes: -1
Reputation: 50034
As another option, looping once but checking the next two letters ahead will work, and the loop is smaller since you don't have to check the last two characters AND you can break as soon as you find a hit:
for i in range(0, len(instring)-2):
if (instring[i] == instring[i+1] == instring[i+2]):
print(f"{instring[i]} occurs three or more times.")
break
Optionally, if you need to know the value or position in the string where these sequences appear, you could generate a list that holds the index of the letter that start a three-in-a-row sequence:
print([[i,c] for i,c in enumerate(instring) if i < len(instring)-2 and (c == instring[i+1] == instring[i+2])])
This will generate a list of lists with the letter and the position in the word where sequence of 3 is found.
Upvotes: 5
Reputation: 66371
You don't need a nested loop - just keep track of the last character you saw and use a counter
def atleast3(s):
count = 0
last = None
for c in s:
if c == last:
count += 1
if count >= 3:
return True
else:
count = 1
last = c
return False
Upvotes: 3
Reputation: 177
One loop can work
string = 'hellooo'
res = ''
prev_item = ''
for item in string:
if item == prev_item:
res += '1'
else:
res += '0'
prev_item = item
print(res) #'0001011'
if '11' in res:
print('Yes')
else:
print('No')
Upvotes: 1