【问题标题】:How can I replace substrings without replacing all at the same time? Python如何替换子字符串而不同时替换所有子字符串? Python
【发布时间】:2014-05-18 08:11:04
【问题描述】:

我编写了一个非常好的程序,它使用文本文件作为词库,用于从句子骨架生成句子。一个例子:

骷髅
“名词擅长动词动词”
可以通过搜索名词和动词的词库来代替骨架中的“名词”和“动词”来造句。我想得到类似的结果
“狗很会捡棍子”

不幸的是,方便的 replace() 方法是为提高速度而设计的,而不是考虑自定义函数。我创建了一些方法来完成从正确的库中选择随机单词的任务,但是做类似骨架 = 骨架.replace('noun', getNoun(file.txt)) 的方法会用 getNoun 的单个调用替换 'noun' 的所有实例(),而不是为每个替换调用它。所以句子看起来像

“狗善于捉狗”

如何解决 replace() 的这个特性,并让我的方法在每次替换时都被调用?我的最小长度代码如下。

import random

def getRandomLine(rsv):
    #parameter must be a return-separated value text file whose first line contains the number of lines in the file.
    f = open(rsv, 'r') #file handle on read mode
    n = int(f.readline()) #number of lines in file
    n = random.randint(1, n) #line number chosen to use
    s = "" #string to hold data
    for x in range (1, n):
        s = f.readline()
    s = s.replace("\n", "")
    return s

def makeSentence(rsv):
    #parameter must be a return-separated value text file whose first line contains the number of lines in the file.
    pattern = getRandomLine(rsv) #get a random pattern from file
    #replace word tags with random words from matching files
    pattern = pattern.replace('noun', getRandomLine('noun.txt'))
    pattern = pattern.replace('verb', getRandomLine('verb.txt'))

    return str(pattern);

def main():
    result = makeSentence('pattern.txt');
    print(result)

main()

【问题讨论】:

  • “不幸的是,方便的 replace() 方法是为提高速度而设计的,而不是考虑自定义函数。” - 不,行为只是参数传递如何工作的自然结果。无论您如何实现replace,在调用replace 时,getRandomLine 调用已经结束。 replace 不知道它正在查看的字符串来自 getRandomLine 调用,并且无法重复调用。
  • 这很有趣。您有解决问题的建议吗?

标签: python regex string replace substring


【解决方案1】:

re 模块的re.sub 函数可以完成str.replace 的工作,但功能要多得多。特别是,它提供了传递替换函数而不是字符串的能力。该函数在每次匹配时调用一次,并以匹配对象作为参数,并且必须返回将替换匹配项的字符串:

import re
pattern = re.sub('noun', lambda match: getRandomLine('noun.txt'), pattern)

这里的好处是增加了灵活性。不利的一面是,如果您不了解正则表达式,则替换将'noun' 解释为正则表达式这一事实可能会引起意外。例如,

>>> re.sub('Aw, man...', 'Match found.', 'Aw, manatee.')
'Match found.e.'

如果您不了解正则表达式,您可能希望使用re.escape 创建一个正则表达式,该正则表达式将匹配您正在搜索的原始文本,即使该文本包含正则表达式元字符:

>>> re.sub(re.escape('Aw, man...'), 'Match found.', 'Aw, manatee.')
'Aw, manatee.'

【讨论】:

  • 非常感谢!这正是我所需要的!
【解决方案2】:

我不知道你是要编辑你的代码还是写新代码,所以我写了新代码:

import random
verbs = open('verb.txt').read().split()
nouns = open('noun.txt').read().split()

def makeSentence(sent):
    sent = sent.split()
    for k in range(0, len(sent)):
            if sent[k] == 'noun':
                    sent[k] = random.choice(nouns)
            elif sent[k] == 'nouns':
                    sent[k] = random.choice(nouns)+'s'
            elif sent[k] == 'verbing':
                    sent[k] = random.choice(verbs)

    return ' '.join(sent)

var = raw_input('Enter: ')
print makeSentence(var)

运行如下:

$ python make.py
Enter: the noun is good at verbing nouns
the mouse is good at eating cats

【讨论】:

  • 这是一个不错的解决方案,但我认为通过正则表达式搜索要好得多,因为每个词性只需要搜索一次。您不必寻找“动词”和“动词”。只是“动词”。
猜你喜欢
  • 2022-01-11
  • 2018-03-26
  • 2021-03-17
  • 2014-06-09
  • 2014-10-12
  • 1970-01-01
  • 2015-11-09
  • 2016-12-24
  • 2021-11-23
相关资源
最近更新 更多