【问题标题】:Delete the repetition of a specific word in a row删除一行中特定单词的重复
【发布时间】:2018-07-27 09:19:24
【问题描述】:

例如我有一个字符串:

my_str = 'my example example string contains example some text'

我想要做的 - 删除特定单词的所有重复项(仅当它们连续出现时)。结果:

my example string contains example some text

我尝试了下一个代码:

import re
my_str = re.sub(' example +', ' example ', my_str)

my_str = re.sub('\[ example ]+', ' example ', my_str)

但它不起作用。 我知道有很多关于 re 的问题,但我仍然无法将它们正确地应用到我的案例中。

【问题讨论】:

  • 你能做的最好的事情就是阅读正则表达式教程,基本的东西就足够了。
  • 一个需要使用带有动态值的单词边界的问题并不容易通过正则表达式教程来解决。此外,Regular Expression For Consecutive Duplicate Words 不包含 Python 实现,这对于那些不熟悉将原始字符串文字用于正则表达式模式的最佳实践的人来说很棘手。
  • @WiktorStribiżew:解决一般情况确实不是那么容易,但问题是删除一个相对简单的特定重复词:\bexample(?:\s+example)+\b,然后构建如果考虑到 Python 中广泛使用的众所周知的格式化字符串,它动态地使用捕获组和反向引用几乎是过度设计的。问题是提问者在写一个问题和等待一个主题的答案上花费的时间比阅读关于这个主题的教程要多。此外,他没有进行任何搜索(请参阅两种模式和回避:“我知道有...等等”)。
  • @WiktorStribiżew:也就是说,我的第一条评论与其说是责备不如说是建议。

标签: python regex string python-3.x char


【解决方案1】:

您需要创建一个组并对其进行量化:

import re
my_str = 'my example example string contains example some text'
my_str = re.sub(r'\b(example)(?:\s+\1)+\b', r'\1', my_str)
print(my_str) # => my example string contains example some text

# To build the pattern dynamically, if your word is not static
word = "example"
my_str = re.sub(r'(?<!\w)({})(?:\s+\1)+(?!\w)'.format(re.escape(word)), r'\1', my_str)

Python demo

我添加了单词边界,因为 - 根据原始代码中的空格判断 - 预期会匹配整个单词。

regex demo here

  • \b - 单词边界(替换为 (?&lt;!\w) - 在允许当前位置之前没有单词字符 - 在动态方法中,因为 re.escape 也可能支持“单词”,例如 .word. 然后 \b 可能会停止正则表达式来自匹配)
  • (example) - 第 1 组(与替换模式中的 \1 一起引用): example
  • (?:\s+\1)+ - 出现 1 次或多次
    • \s+ - 1+ 个空格
    • \1 - 对 Group 1 值的反向引用,即 example
  • \b - 单词边界(替换为 (?!\w) - 当前位置后不允许出现单词字符)。

请记住,在 Python 2.x 中,如果您需要使 \b 字边界识别为 Unicode,则需要使用 re.U

【讨论】:

  • @Mikhail_Sam 我添加了代码来处理单词是动态值的情况,甚至在“单词”可能以非单词字符开头/结尾的情况下。
【解决方案2】:

正则表达式\b(\w+)(?:\s+\1)+\b\b(example)(?:\s+\1)+\b 替换:\1

详情:

  • \b 在单词边界处断言位置
  • \w 匹配任意单词字符(等于[a-zA-Z0-9_]
  • \s 匹配任何空白字符
  • + 匹配一次到无限次
  • \1 第 1 组。

Python 代码

text = 'my example example string contains example some text'

text = re.sub(r'\b(\w+)(?:\s+\1)+\b', r'\1', text)

输出:

my example string contains example some text

Code demo

【讨论】:

  • 据我了解,它会删除任何重复的单词吗?我目前不确定,我需要什么,但可能只是具体的:)
【解决方案3】:

您也可以在纯 Python(没有 regex)中执行此操作,方法是创建一个单词列表,然后生成一个新的 string - 应用您的规则。

>>> words = my_str.split()
>>> ' '.join(w for i, w in enumerate(words) if w != words[i-1] or i == 0)
'my example string contains example some text'

【讨论】:

  • 实际上我需要为文本中的每个字符串实现它,因此最好使用一行答案:) 无论如何,我喜欢纯 python 解决方案!谢谢!
  • @Mikhail_Sam “对于文本中的每个字符串”是什么意思?
  • 我的意思是我有字符串列表。所以将用循环包装它(或使用列表理解)。所以我担心使用这种方法会很笨重
  • @Mikhail_Sam 我明白了,在这种情况下,您可以创建一个新的单词列表,然后执行' '.join(...)。或者,如果效率不是太重要,那么您可以简单地将words 替换为 my_str.split() 的两次出现
【解决方案4】:

为什么不使用 .replace 函数:

my_str = 'my example example string contains example some text'
print my_str.replace("example example", "example")

【讨论】:

  • 问题是关于一般情况
  • 它们可以是三个或四个或连续的任何一个
猜你喜欢
  • 2018-11-20
  • 1970-01-01
  • 1970-01-01
  • 2012-02-06
  • 1970-01-01
  • 2016-04-28
  • 1970-01-01
  • 1970-01-01
  • 2020-04-02
相关资源
最近更新 更多