简体   繁体   English

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

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

I'm trying to program a vocabulary game.我正在尝试编写一个词汇游戏。 Let me say at the outset that I'm a completely rookie programmer!首先让我说我是一个完全菜鸟程序员!

I am using a regular expression to hide a word, which I have to guess.我正在使用正则表达式来隐藏一个我必须猜测的单词。

Take for example the chosen_word :selected_word 为例

'TO CRANK (STH) UP'

With RegExs I manage to hide the keywords and I have hidden_word as follows:使用 RegExs 我设法隐藏关键字,并且我有hidden_word如下:

TO _ _ _ _ _ (STH) _ _

With the RegEx findall() and the filter() methods I get a list of hidden_letters :使用 RegEx findall()filter()方法,我得到一个hidden_letters列表:

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

The idea is that we now choose one letter from this list randomly to reveal to the user:这个想法是我们现在从这个列表中随机选择一个字母来显示给用户:

chosen_letter = random.choice(hidden_letters)

n = hidden_letters.index(chosen_letter) + 1

Now the chosen letter's n maps beautifully onto its corresponding underscores in the hidden_word .现在所选字母的n完美地映射到hidden_word中相应的下划线。 For example, if the game has randomly chosen the letter 'R', then n will be '2', and in the hidden_word this letter's position is at the 2nd underscore.例如,如果游戏随机选择了字母“R”,那么n将是“2”,并且在hidden_word中,该字母的 position 位于第二个下划线。

I am stuck at this stage now.我现在被困在这个阶段。 I want to replace the n th underscore of hidden_word with the chosen_letter .我想用 selected_letter 替换hidden_wordn个下划线。 I'm thinking of using either the .replace() method, or the RegEx re.sub() method, but I don't know how to start off.我正在考虑使用.replace()方法或 RegEx re.sub()方法,但我不知道如何开始。

Could someone please give me hints?有人可以给我提示吗?

Many thanks in advance!!提前谢谢了!!

I would approach this a bit differently:我会以不同的方式处理这个问题:

The state at each point in time is defined by:每个时间点的 state 定义为:

  • the full phrase (to be guessed),完整的短语(待猜),
  • a set of hidden words,一组隐藏的单词,
  • letters guessed so far (or to be revealed to the user).到目前为止猜到的字母(或要向用户显示的字母)。

The you can define a show() function with these three quantities:您可以使用以下三个数量定义show() function:

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)

With this, you can write tests, including doctests.有了这个,您可以编写测试,包括 doctests。 That will make your code much easier to document, debug, test and use.这将使您的代码更容易记录、调试、测试和使用。

Some examples (which could be included as doctests in the docstring of show ):一些示例(可以作为文档测试包含在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'

Given you're a rookie, I'd thought throw my hat in and do it without regex and attempt to explain.鉴于您是新手,我想把我的帽子扔进去,不使用正则表达式并尝试解释。 Maybe only read this once you've had your go.也许只有在您拥有 go 后才阅读此内容。 Your question title can be answered with:您的问题标题可以这样回答:

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

It converts the string to a list of letters which you can replace by index n and then joins it back up.它将字符串转换为可以用索引n替换的字母列表,然后将其连接起来。

I've also given the rest a go to show you more python options.我还为 rest 提供了 go 以向您展示更多 python 选项。

As you're managing the state, you might want to think about using a class .在管理 state 时,您可能需要考虑使用 class It helps you wrap all the functions and attributes together into one object with a purpose - playing your Vocabulary Game.它可以帮助您将所有功能和属性打包到一个 object 中,目的是为了玩您的词汇游戏。 I recommend looking into them.我建议调查他们。 Here is one for the game:这是游戏中的一个:

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}")

The __init__ section runs whenever we make new game instances and takes three arguments, (self, chosen_words, hidden_words) . __init__部分在我们创建新游戏实例时运行,并使用三个 arguments, (self, chosen_words, hidden_words) The use of self references the current class instance (or game) and we can use it to set and retrieve attributes to the class, in this case, to remember our words and sentences.使用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))) gets all unique letters in the hidden words by joining them into one string and using sets to convert them into the unique letters. list(set(''.join(words)))通过将隐藏单词中的所有唯一字母连接成一个字符串并使用集合将它们转换为唯一字母来获取它们。 I convert this back into a list for ease of use later.我将其转换回列表以便以后使用。

We then apply a function to mask the words with '_'.然后我们应用 function 用“_”屏蔽单词。

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

This goes through each word in the sentence and replaces it with '_' for the length of the word, if it exists in hidden words.这会遍历句子中的每个单词,如果单词存在于隐藏单词中,则将其替换为单词长度的“_”。 Then it joins it back up.然后它重新加入它。 Now we have our start state.现在我们有了开始 state。

The last thing to do is to try a letter.最后要做的是尝试一个字母。 We do this by defining a method (function on a class) def try_letter(self, letter=None): .我们通过定义一个方法(类上的函数) def try_letter(self, letter=None):来做到这一点。 If no letter is provided, we pick a random one from the unique missing letters we defined earlier.如果没有提供字母,我们会从之前定义的唯一缺失字母中随机选择一个。 The we go through each letter in the original sentence and masked sentence together using zip and when the original letter is our chosen letter, we replace the one in our masked sentence.我们使用 zip 将原始句子中的每个字母和掩码句子中的每个字母zip一起使用,当原始字母是我们选择的字母时,我们替换掩码句子中的那个。

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

Then remove the letter form our hidden letters list:然后从我们的隐藏字母列表中删除字母:

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

Finally, we print result out using f-strings .最后,我们使用f-strings打印结果。 Now, we can play the game!现在,我们可以玩游戏了!

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

game = VocabularyGame(chosen_word, words)

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

Trying a letter 7 times for i in range(7): game.try_letter() Outputs: 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

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

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