Home > Software engineering >  Iterating over indexes of a list to see if they are equal
Iterating over indexes of a list to see if they are equal

Time:12-11

i am trying to write a function that will analyze a string to check if it contains two of the same letter in a row. i wrote the function for it but it doesnt work, any idea why?

import itertools
def double_letters(word):
word = list(word)
for index, item in enumerate(word):
    for next_item in word[index   1:]:
        if item == next_item:
            return True
        else:
            return False

CodePudding user response:

You're doing a few weird things here, but the main one is the secondary loop. Why do you need that if you have the index? You know the next index is just 1 and you don't even use both (index & value) here.

The second biggest problem is returning false if the characters don't match; this will return the matching result only for the first two characters, but you're looking for the first match, so you should only return on a match. You can use a variable to track this, but you can also simply return true when needed and return false if that condition is never met.

Last, you don't need enumerate, although it's fine. For this approach I would just enumerate to the 2nd last index (enumerate(word[0:len(word)-1]). Or, don't use enumerate like in the example below:

import itertools
def double_letters(word):
    word = list(word)
    for index in range(len(word)-1):
        if word[index] == word[index 1]:
            return True
    return False;
print(double_letters('world hello '))

CodePudding user response:

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

CodePudding user response:

If you don't have an equality once, you cannot stop directly by returning false. You need to wait the end. Also don't need a nested loop, use zip to iterate on 2 consecutive chars of a string

def double_letters(word):
    for current_ch, next_ch in zip(word, word[1:]):
        if current_ch == next_ch:
            return True
    return False
  • Related