如果不是某个单词,请在字符串中放置随机字符



例如,我有以下字符串:

Hello how are you today, [name]?

我该如何在随机选择的单词之间随机放置字符,而不是[姓名]?我已经有了下面的代码,但我希望有更好的方法

string = 'Hello how are you today, [name]?'
characters = 'qwertyuioplkjhgfdsazxcvbnm,. '
arr = string.rsplit(" ")
for i in range(0, len(arr)):
    x = arr[i]
    if x == '[name]':
        continue
    if (random.randint(0,2)==1) :
        rnd=random.randint(1,len(x)-2)
        tmp1 = random.randint(0,len(characters))
        rndCharacter = characters[tmp1:tmp1+1]
        x = x[0:rnd] + rndCharacter + x[rnd+1:]
        arr[i] = x
" ".join(arr)
> Hellio how are yoy todsy, [name]?"

尽管这会用另一个随机字符替换该字符。我该如何让它随机替换或在字符之后或之前放置一个随机字符?

基本上,我只是想模拟一种打字错误生成器。

感谢

到目前为止我的代码更新:

string = 'Hey how are you doing, [name]?'
characters = 'aeiou'
arr = string.rsplit(" ")
for i in range(0, len(arr)):
    x = arr[i]
    if x == '[name]': continue
    if len(x) > 3:
        if random.random() > 0.7:
            rnd = random.randint(0,len(x)-1)
            rndCharacter = random.choice(characters)
            if random.random() > 0.7:
                x = x[0:rnd] + rndCharacter + x[rnd+1:]
            else:
                x = x[:rnd] + rndCharacter + x[rnd:]
            arr[i] = x
    else:
        if random.random() > 0.7:
            rnd = random.randint(0,len(x)-1)
            rndCharacter = random.choice(characters)
            x = x[:rnd] + rndCharacter + x[rnd:]
            arr[i] = x
print " ".join(arr)
> Hey houw are you doiang, [name]?

更新:

也许我对代码的最后更新,希望这能在未来的中帮助一些人

def misspeller(word):
    typos = { 'a': 'aqwedcxzs',
              'b': 'bgfv nh',
              'c': 'cdx vf',
              'd': 'desxcfr',
              'e': 'e3wsdfr4',
              'f': 'fredcvgt',
              'g': 'gtrfvbhyt',
              'h': 'hytgbnju',
              'i': 'i8ujko9',
              'j': 'juyhnmki',
              'k': 'kiujm,lo',
              'l': 'loik,.;p',
              'm': 'mkjn ,',
              'n': 'nhb mjh',
              'o': 'o9ikl;p0',
              'p': 'p0ol;[-',
              'q': 'q1asw2',
              'r': 'r4edft5',
              's': 'swazxde',
              't': 't5rfgy6',
              'u': 'u7yhji8',
              'v': 'vfc bg',
              'w': 'w2qasde3',
              'x': 'xszcd',
              'y': 'y6tghu7',
              'z': 'zaZxs',
              ' ': ' bvcnm',
              '"': '"{:?}',
              ''': '[;/']',
              ':': ':PL>?"{',
              '<': '<LKM >',
              '>': '>:L<?:',
              ';': ';pl,.;[',
              '[': '[-p;']=',
              ']': '=['',
              '{': '{[_P:"}+',
              '}': '}=[']=',
              '|': '|]'',
              '.': '.l,/;',
              ',': ',lkm.'
            }
    index = random.randint(1,len(word)-1)
    letter = list(word[:index])[-1].lower()
    try:
        if random.random() <= 0.5:
            return word[:index] + random.choice(list(typos[letter])) + word[index:]
        else:
            return word[:index-1] + random.choice(list(typos[letter])) + word[index:]
    except KeyError:
        return word
def generate(self, s, n, safe_name):
    misspelled_s = ''
    misspelled_list = []
    for item in s.split(' '):
        if n:
            if safe_name in item:
                misspelled_list.append(item)
            else:
                r = random.randint(0,1)
                if r == 1 and len(re.sub('[^A-Za-z0-9]+', '', item)) > 3:
                    misspelled_list.append(misspeller(item))
                    n -= 1
                else:
                    misspelled_list.append(item)
        else:
            misspelled_list.append(item)
    return ' '.join(misspelled_list)
import random
def misspeller(word):
    characters = 'qwertyuioplkjhgfdsazxcvbnm,. '
    rand_word_position = random.randint(-1,len(word))
    rand_characters_position = random.randint(0,len(characters)-1)
    if rand_word_position == -1:
        misspelled_word = characters[rand_characters_position] + word 
    elif rand_word_position == len(word):
        misspelled_word = word + characters[rand_characters_position] 
    else:
        misspelled_word = list(word)
        misspelled_word[rand_word_position] = characters[rand_characters_position]
        misspelled_word = ''.join(misspelled_word)        
    return misspelled_word
s = 'Hello how are you today, [name]?'
misspelled_s = ''
misspelled_list = []
for item in s.split(' '):
    if '[name]' in item:
        misspelled_list.append(item)
    else:
        misspelled_list.append(misspeller(item))
misspelled_s = ' '.join(misspelled_list)
print misspelled_s

我从misspelled_s得到的例子有:

'Hellk howg ars youf poday, [name]?'
'Heylo how arer y,u todab, [name]?'
'Hrllo hfw  are zyou totay, [name]?'

编辑以清除第一份副本中的几个错误和遗漏。

编辑2如果您不希望每个单词都受到影响,您可以通过以下方式修改for循环:

for item in s.split(' '):
    n = random.randint(0,1)
    if '[name]' in item:
        misspelled_list.append(item)
    elif n == 1:
        misspelled_list.append(misspeller(item))
    else:
        misspelled_list.append(item)

您可以通过更改生成n的方式来修改单词被修改的概率,例如n = random.randint(0,10)

如果你想把一个字母放在前面或后面,而不是替换,只需修复拼接中的索引,这样它们就不会跳过一个字母-即使用

x = x[:rnd] + rndCharacter + x[rnd:]

这样,新字符将插入中间,而不是替换现有字符。

此外,您可以使用rndCharacter = random.choice(characters),而不是像那样使用tmp1

我认为@sgallen的答案会起作用,但我有一些提示(针对您以前的代码,以及以后的代码)。

for i in range(0, len(arr)):
    x = arr[i]
# is the same as
for i,x in enumerate(arr):

else:
    if random...:
# to
elif random...:

使用string作为变量的名称不是一个好的做法。原因是,有一个string模块。由于字符串常量的存在,它甚至可以派上用场。备选方案可以是inpdatasentence

# For example
>>> import string
>>> string.lowercase
'abcdefghijklmnopqrstuvwxyz'

顺便说一句,如果有人注意到上面的错误,请留下评论。谢谢

您也可以使用split('[name]'),并处理子字符串,这样您就可以确保(请参阅下面的注释)不会更改'[name]'

您可能在每次[name]发生时都会遇到拆分问题,捕获一些较长名称的子字符串,但如果您:

  • 使用大写的真实姓名和常用姓名(如Jonh)
  • 避免使用类似的名称

然后以下代码应该可以正常工作:

def typo(string):
    index = random.randint(1,len(string)-1)   # don't change first or last
    return string[:index] + random.choice(characters) + string[index:]
def generate(string, n, safe_name):
    sub_strings = string.split(safe_name)
    while n:
        sub_index = random.randint(0,len(sub_strings) - 1)
        sub = sub_strings[sub_index]
        if len(sub) <= 2:   # if too short don't change
            continue
        sub_strings[sub_index] = typo(sub)
        n -= 1
    return safe_name.join(sub_strings)

添加3个新随机特征的示例:

>>> string = 'Hello how are you today, Alice?'
>>> generate(string, 3, 'Alice')
'Hellov howj are yoiu today, Alice?'

名称出现不止一次:

>>> string = 'Hello Alice, how are you today, Alice?'
>>> generate(string, 3, 'Alice')
'Hello Alice, hoiw arfe you todayq, Alice?'

对于您给出的示例,我们可以将其拆分为逗号,并将拼写错误放在字符串的第一部分。

如果这是正确的,你需要在生成拼写错误之前随机做三件事:

  • 选择在哪个字符上或附近打字
  • 选择拼写错误的字符
  • 从三个操作中选择一个-替换、前缀、附加

这个合适吗?

(顺便说一句,由于你熟悉随机,我没有给出任何代码。)

您"希望有更好的方法"。好吧,这里有一些建议,以及一些演示这些建议的代码。其中一些建议是让代码更具Python风格或更易于阅读,而不仅仅是改变字符串的机制。

  1. 对正则表达式使用模块re来检测"[name]"。只要你有更多的关键词,这将带来回报
  2. for x in string.rsplit(" ")是一种更像蟒蛇的循环方式
  3. 获取实数随机数,并与0.0-1.0范围内的概率设置进行比较。比获取整数0,1更灵活
  4. 按照其他人的建议使用x[:rnd] + ... + x[rnd:x],以便于字符串操作
  5. 使用x if condition else y可以在备选方案之间进行简洁的选择,在这种情况下,可以在导致覆盖的索引和导致插入的索引之间进行选择
  6. 您的示例输出显示在"you"中插入了一个拼写错误,但您的示例代码仅在len(x) > 3中插入拼写错误。我遵循你的代码,但这很容易更改

希望这能有所帮助。

import random
import re
string = 'Hello how are you today, [name]?'
characters = 'qwertyuioplkjhgfdsazxcvbnm,. '
words = []
for x in string.rsplit(" "):
    if    None == re.search('[^]]*[[a-z]+].*', x) 
      and len(x) > 3 and random.random()<=0.5:
        # rnd: index of char to overwrite or insert before
        rnd = random.randint(2,len(x)-2)
        # rnd1: index of 1st char after modification
        # random.random <= 0.x is probability of overwriting instead of inserting
        rnd1 = rnd + 1 if random.random() <= 0.5 else 0
        x = x[:rnd] + random.choice(characters) + x[rnd1:]
    words.append(x)
typos = " ".join(words)
print typos

更新:修复了代码中的缩进错误。

更新2:使选择覆盖与插入的代码更加简洁。

最新更新