获取字符串中重复字母的索引

Getting index of duplicate letters in a string

from graphics import *
import random 

def hangman(word):
    returnStuff = {'again':0, '1st':1}

    alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
                'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']

    win = GraphWin("Hangman", 800, 550)
    win.setBackground("yellow")

    titleText = Text(Point(400,50), 'HANGMAN')
    titleText.setSize(24)
    titleText.setStyle('bold')
    titleText.draw(win)

    #Building the hangman base
    base = Line(Point(120,350),Point(230,350))
    base.draw(win)
    stand = Line(Point(175,350),Point(175,150))
    stand.draw(win)
    stand2 = Line(Point(175,150),Point(250,150))
    stand2.draw(win)
    stand3 = Line(Point(250,150),Point(250,180))
    stand3.draw(win)

    #drawing the empty lines for the word
    x1 = 150
    x2 = 180
    l = 0
    print(word)
    while l< len(word):
        wordLine = Line(Point(x1, 420),Point(x2,420))
        wordLine.draw(win)
        l+=1
        x1+=40
        x2+=40

    guessCounter = 0
    textCheck = 0
    invalidText = Text(Point(600,100), 'You did not enter a valid letter.')
    invalidText.setTextColor('red')
    indexes = []
    while guessCounter < 6:
        #text entry box
        textEntry = Entry(Point(600,180),10)
        textEntry.draw(win)
        guessText = Text(Point(600,150), 'Guess a letter:')
        guessText.draw(win)
        #user has to click this box to confirm the letter
        enterBox = Rectangle(Point(580,200), Point(620,220))
        enterBox.setFill('white')
        enterBox.draw(win)
        clickText = Text(Point(600,210), 'Enter')
        clickText.draw(win)

        click = win.getMouse()
        x = click.getX()
        y = click.getY()

        if 580 < x < 620 and 200 < y < 220:
            guess = textEntry.getText().lower().strip()
            if guess not in alphabet:
                if textCheck == 0:
                    invalidText.draw(win)
                    textCheck = 1

            else:
                if textCheck == 1:
                    invalidText.undraw()
                    textCheck = 0
                for letter in word:
                    if letter == guess:
                        indexes.append(word.index(guess))
                        print(indexes)


    win.getMouse()

    win.close()

    return returnStuff 

#list with various words pertaining to nanotechnology
words = ['nanotechnology', 'science', 'nanometre' , 'strength', 'chemistry',
         'small', 'molecule', 'light' , 'weight', 'technology', 'materials',
         'property', 'physics', 'engineering', 'matter', 'waterloo', 'nanobot',
         'reaction', 'structure', 'cells']

#picks a random word from the list
word = random.choice(words)

#this variable ensures it opens the game the first time
initialCall = 1
#stores the returnValue for the first call
returnValue = hangman(word)

#sets the initialCall to 0 after first call 
if returnValue['1st']==1:
    initialCall=0

#Calls the game function again if user wishes
while initialCall == 1 or returnStuff['again'] == 1:
    returnValue = hangman(word)

我正在 Python 图形中制作刽子手。对于庞大的代码块,我深表歉意,一切正常,我只是认为它一定有用。我关心的代码部分是这样的:

            else:
                if textCheck == 1:
                    invalidText.undraw()
                    textCheck = 0
                for letter in word:
                    if letter == guess:
                        indexes.append(word.index(guess))
                        print(indexes)

当用户猜测的字母在字母表中时,将执行此代码块,然后我 运行 遍历所选单词中的每个字母,如果在任何时候单词中的字母相同作为猜测字母,我将该字母的索引存储在一个空列表中,以便我可以使用它来告诉计算机在空行上绘制字母的位置。

它工作正常,除非单词中有重复的字母。例如,工程学有 3 个 es。不幸的是, .index() 只记录字母第一次出现时的索引,而忽略其他字母。 解决这个问题的方法是什么,这样我就可以获得该词中所有 3 个 es 的索引,而不是仅第一个 e 的 3 个索引。出于测试目的,我打印了所选的控制台上的单词和索引列表,这样我就可以看到发生了什么,所以我实际上不必猜测一个字母。

你可以这样做

def indexes(word,letter):
    for i,x in enumerate(word):
        if x == letter:
            yield i

测试

>>> list( indexes("engineering","e") )
[0, 5, 6]
>>> 

这个函数是一个 generator, that is a lazy function that only give result when asked for then, to get a individual result you use next, the functions is execute until the first yield 然后 return 结果并停止它的执行并记住它在哪里,直到另一个调用 next 在 点从前一个点直到下一个 yield,如果不再引发 StopIteration,例如:

>>> word="engineering"
>>> index_e = indexes(word,"e")
>>> next(index_e)
0
>>> print(word)
engineering
>>> next(index_e)
5
>>> next(index_e)
6
>>> next(index_e)
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    next(index_e)
StopIteration
>>> 

要使用此函数的结果更新列表,您可以使用扩展方法

>>> my_list=list()
>>> index_e = indexes(word,"e")
>>> my_list.extend( index_e )
>>> my_list
[0, 5, 6]
>>> 

generator 用于它们的结果只是其他东西的中间步骤的情况,因为它们使用最少的内存,但在这种情况下,也许你想要整个东西,所以将它用作第一个示例或重新制作像这样 return 首先对一个列表起作用

def indexes(word,letter):
    result = list()
    for i,x in enumerate(word):
        if x == letter:
            result.append(i)
    return result

对不起,如果我把你和 yield 搞混了。