替换字符串的第 n 个字符(RegEx 与否)

replace the nth character of a string (RegEx or not)

我正在尝试编写一个词汇游戏。先声明一下,我是一个彻头彻尾的菜鸟程序员!

我正在使用正则表达式来隐藏一个我必须猜测的词。

chosen_word为例:

'TO CRANK (STH) UP'

使用正则表达式,我设法隐藏了关键字,并且 hidden_word 如下:

TO _ _ _ _ _ (STH) _ _

使用 RegEx findall()filter() 方法我得到了 hidden_letters:

['C', 'R', 'A', 'N', 'K', 'U', 'P']

我们现在的想法是从这个列表中随机选择一个字母来显示给用户:

chosen_letter = random.choice(hidden_letters)

n = hidden_letters.index(chosen_letter) + 1

现在所选字母的 n 漂亮地映射到 hidden_word 中相应的下划线。例如,如果游戏随机选择了字母 'R',那么 n 将是 '2',而在 hidden_word这个字母的位置在第2个下划线。

我现在卡在这个阶段了。我想用 chosen_letter[=59= 替换 nth 下划线 hidden_word ].我正在考虑使用 .replace() 方法或 RegEx re.sub() 方法,但我没有不知道如何开始。

有人可以给我提示吗?

非常感谢!!

我会以不同的方式处理这个问题:

每个时间点的状态定义为:

  • 完整短语(待猜),
  • 一组隐藏词,
  • 到目前为止猜到的字母(或向用户透露)。

您可以使用这三个量定义一个 show() 函数:

def show(phrase, hidden_words, letters_guessed):
    parts = [
        ''.join([
            c if c in letters_guessed else '-' for c in w
        ]) if w in hidden_words else w
        for w in phrase.split()
    ]
    return ' '.join(parts)

有了这个,您可以编写测试,包括 doctests。这将使您的代码更易于记录、调试、测试和使用。

一些示例(可以作为文档测试包含在 show 的文档字符串中):

phrase = 'TO PIPE (STH) UP AND PIPE DOWN'
hidden_words = {'PIPE', 'UP'}

>>> show(phrase, hidden_words, {})
'TO ---- (STH) -- AND ---- DOWN'

>>> show(phrase, hidden_words, set('I'))
'TO -I-- (STH) -- AND -I-- DOWN'

>>> show(phrase, hidden_words, set('PI'))
'TO PIP- (STH) -P AND PIP- DOWN'

考虑到您是新手,我想把我的帽子扔进去,不使用正则表达式并尝试解释。也许只有在你开始之后才阅读这篇文章。您的问题标题可以这样回答:

def replace_nth_char(string, n, replacement):
    n -= 1
    l_string = list(string)
    l_string[n] = replacement
    return ''.join(l_string)

它将字符串转换为可以用索引替换的字母列表 n,然后将其连接起来。

我还尝试了其余部分,向您展示了更多 python 选项。

在管理状态时,您可能需要考虑 using a class。它可以帮助您将所有功能和属性打包到一个 object 中,目的是玩您的词汇游戏。我建议调查一下。这是游戏的一个:

import random


class VocabularyGame():
    def __init__(self, chosen_words, hidden_words):
        self.chosen_words = chosen_words
        self.hidden_words = hidden_words
        self.hidden_letters = list(set(''.join(words)))
        self.masked_sentence = self.mask_words(chosen_words, hidden_words)
        print(f"Game start: {self.masked_sentence}")
        
    def mask_words(self, sentence, masks):
        return ' '.join(['_'*len(w) if w in masks else w for w in sentence.split(' ')])
    
    def try_letter(self, letter=None):
        if letter is None:
            letter = random.choice(self.hidden_letters)
        self.masked_sentence = ''.join(
            [c if c== letter else m for m, c in zip(self.masked_sentence, self.chosen_words)]
        )
        self.hidden_letters = [l for l in self.hidden_letters if l != letter]
        print(f"Trying letter {letter}...\nRemaining letters: {self.masked_sentence}")

每当我们创建新游戏实例时,__init__ 部分就会运行,并接受三个参数,(self, chosen_words, hidden_words)self 的使用引用了当前的 class 实例(或游戏),我们可以使用它来设置和检索 class 的属性,在这种情况下,以记住我们的单词和句子。

    def __init__(self, chosen_words, hidden_words):
        self.chosen_words = chosen_words
        self.hidden_words = hidden_words
        self.hidden_letters = list(set(''.join(hidden_words)))
        self.masked_sentence = self.mask_words(chosen_words, hidden_words)
        print(f"Game start: {self.masked_sentence}")

list(set(''.join(words))) 通过将它们连接成一个字符串来获取隐藏单词中的所有唯一字母,然后 using sets 将它们转换为唯一字母。我将其转换回列表以便于以后使用。

然后我们应用一个函数来屏蔽带有“_”的单词。

    def mask_words(self, sentence, masks):
        return ' '.join(['_'*len(w) if w in masks else w for w in sentence.split(' ')])

这遍历句子中的每个单词,如果它存在于隐藏单词中,则将其替换为单词长度的“_”。然后它加入备份。现在我们有了开始状态。

最后要做的是尝试一封信。我们通过定义一个方法(class 上的函数)def try_letter(self, letter=None): 来做到这一点。如果没有提供字母,我们会从我们之前定义的唯一缺失字母中随机选择一个。 我们使用 zip 一起检查原始句子和掩码句子中的每个字母,当原始字母是我们选择的字母时,我们替换掩码句子中的字母。

        self.masked_sentence = ''.join(
            [c if c==letter else m for m, c in zip(self.masked_sentence, self.chosen_words)]
        )

然后从我们的隐藏字母列表中删除字母:

self.hidden_letters = [l for l in self.hidden_letters if l != letter]

最后,我们使用f-strings打印结果。 现在,我们可以玩游戏了!

chosen_word = "TO CRANK (STH) UP"
words = ['CRANK', 'UP']

game = VocabularyGame(chosen_word, words)

输出:Game start: TO _____ (STH) __

尝试一个字母 7 次 for i in range(7): game.try_letter() 输出:

Trying letter N...
Remaining letters: TO ___N_ (STH) __
Trying letter K...
Remaining letters: TO ___NK (STH) __
Trying letter R...
Remaining letters: TO _R_NK (STH) __
Trying letter P...
Remaining letters: TO _R_NK (STH) _P
Trying letter C...
Remaining letters: TO CR_NK (STH) _P
Trying letter U...
Remaining letters: TO CR_NK (STH) UP
Trying letter A...
Remaining letters: TO CRANK (STH) UP