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

时间:2012-01-21 00:32:03

标签: python

例如,我有以下字符串:

Hello how are you today, [name]?

如何在随机选择的单词之间随意放置字符而不是[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)

6 个答案:

答案 0 :(得分:2)

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

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

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

此外,您可以使用rndCharacter = random.choice(characters)代替tmp1

答案 1 :(得分:2)

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)

答案 2 :(得分:1)

我认为@ 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模块。由于string constants,它甚至可能派上用场。替代方案可以是inpdatasentence

# For example

>>> import string
>>> string.lowercase
'abcdefghijklmnopqrstuvwxyz'

顺便说一句,如果有人注意到上述错误,请发表评论。感谢。

答案 3 :(得分:1)

您也可以使用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?'

答案 4 :(得分:0)

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

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

  • 选择在
  • 上或附近做错字的字符
  • 选择拼写错误字符
  • 选择以下三个操作之一 - 替换,前缀,附加

这符合法案吗?

(顺便说一下,既然你熟悉随机,我没有提供任何代码。)

答案 5 :(得分:0)

你“希望有更好的办法”。好吧,这里有一些建议,还有一些代码展示了这些建议。一些建议是关于使代码更加pythonic或易于阅读,而不仅仅是改变字符串的机制。

  1. 使用module re for regular expressions检测“[名称]”。只要您拥有的关键字多于此关键字,就会产生红利。
  2. for x in string.rsplit(" ")是一种更加抒情的方式来循环使用这些词语。
  3. 获取实数编号的randoms,并与0.0-1.0范围内的概率设置进行比较。比获得整数更灵活0,1。
  4. 按照其他人的建议使用x[:rnd] + ... + x[rnd:x],以便更轻松地操作字符串。
  5. 使用x if condition else y在备选方案之间进行简洁选择,在这种情况下,在导致覆盖的索引和导致插入的索引之间。
  6. 您的示例输出显示在“您”中插入的拼写错误,但您的示例代码仅在len(x) > 3时插入拼写错误。我按照你的代码,但这很容易改变。
  7. 希望这有帮助。

    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:使用选择覆盖与插入的代码更加简洁。