简体   繁体   English

迭代列表的索引以查看它们是否相等

[英]Iterating over indexes of a list to see if they are equal

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.我正在尝试编写一个 function 来分析一个字符串以检查它是否连续包含两个相同的字母。 i wrote the function for it but it doesnt work, any idea why?我为它写了 function 但它不起作用,知道为什么吗?

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

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.你知道下一个索引只是 +1,你甚至不在这里同时使用(索引和值)。

The second biggest problem is returning false if the characters don't match;第二大问题是如果字符不匹配则返回 false; 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.您可以使用变量来跟踪这一点,但您也可以在需要时简单地返回 true,如果从未满足该条件则返回 false。

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:对于这种方法,我只会枚举到倒数第二个索引( enumerate(word[0:len(word)-1] )。或者,不要像下面的示例中那样使用 enumerate:

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

There are three problems with this function, and two of them are on this line:这个function存在三个问题,其中两个在这一行:

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 (ie word[index+1] , not the entire slice word[index+1:]您正在遍历item之后的所有字母,当您关心的唯一next_item紧邻的下一个字母时(即word[index+1] ,而不是整个切片word[index+1:]
  • word[index+1] is going to walk off the edge of the word, leaving you with no next_item to compare. word[index+1]将离开单词的边缘,让您没有next_item可比较。 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.要解决这个问题,您可以检查您是否在最后并对其进行特殊处理,或者您可以在外循环中迭代word[:-1] (除了最后一个字母之外的所有内容)。

The final problem (and the one that's causing your immediate bug) is with this if/else :最后一个问题(以及导致您立即出现错误的问题)是这个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 .无论如何,您将在进行第一次比较后立即返回 - 因此,如果它是前两个字母,则此 function 只会计算一个双字母 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.要解决此问题,请删除else ,并在 function 的最后端return False False,这样我们只有在没有找到返回 True 的理由时才返回 False。

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;使用itertools的解决方案可能是使用groupby ,它将可迭代对象分组为相同的项目; you can check to see if any of the groups are longer than 1 item like this:您可以检查是否有任何组长于 1 项,如下所示:

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:但是编写这种类型的顺序项检查的最简单方法是zip带有自身切片的可迭代对象,如下所示:

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 :或更简单地说,使用any

def double_letters(word):
    return any(item == next_item for item, next_item in zip(word, word[1:]))

If you don't have an equality once, you cannot stop directly by returning false.如果你没有一次相等,你不能通过返回 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也不需要嵌套循环,使用zip迭代字符串的 2 个连续字符

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM