There are three problems with this function, and two of them are on this line:
for next_item in word[index + 1:]:
- You're iterating over all of the letters following
item
, when the only next_item
you're concerned with is the immediate next letter (i.e. word[index+1]
, not the entire slice word[index+1:]
word[index+1]
is going to walk off the edge of the word, leaving you with no next_item
to compare. To fix this, you could check to see if you're at the end and special-case it, or you could just iterate over word[:-1]
(everything but the last letter) in the outer loop.
The final problem (and the one that's causing your immediate bug) is with this if/else
:
if item == next_item:
return True
else:
return False
No matter what, you will immediately return upon making the first comparison -- hence this function will only count a double letter if it's the first two letters. It'll never get to compare anything else. To fix this, remove the else
, and have the return False
happen at the very end of the function, so that we only return False if we haven't found a reason to return True.
All together:
def double_letters(word):
for index, item in enumerate(word[:-1]):
next_item = word[index+1]
if item == next_item:
return True
return False
assert double_letters("hello")
assert not double_letters("abcdef")
A solution with itertools
might be to use groupby
, which groups an iterable into identical items; you can check to see if any of the groups are longer than 1 item like this:
import itertools
def double_letters(word):
for _, g in itertools.groupby(word):
if len(list(g)) > 1:
return True
return False
But the easiest way to write this type of sequential-item check is to zip
the iterable with a slice of itself, like this:
def double_letters(word):
for item, next_item in zip(word, word[1:]):
if item == next_item:
return True
return False
or more simply, using any
:
def double_letters(word):
return any(item == next_item for item, next_item in zip(word, word[1:]))