【问题标题】:Split string by the first occurance from a set of delimiters with Python and regex使用 Python 和正则表达式从一组分隔符中第一次出现拆分字符串
【发布时间】:2016-12-22 22:55:17
【问题描述】:

首先,问题被标记为Pythonregex,但它与这些问题并没有真正的联系——答案可能是高水平的。

目前,我正在使用以下模式拆分具有多个分隔符的字符串。实际上有更多的定界模式,它们也更复杂,但让我们保持简单并将它们限制为 2 个字符 - #*

parts = re.split('#|*', string)

这种方法将字符串aaa#bbb*ccc#ddd拆分为4个子字符串aaabbbcccddd。但是需要通过字符串中最先出现的分隔符或字符串中最频繁出现的分隔符进行拆分。 aaa#bbb*ccc#ddd 应拆分为 aaabbb*cccdddaaa*bbb#ccc*ddd 应拆分为 aaabbb#cccddd

我知道一种直接的方法来实现这一点 - 找出首先出现的分隔符或字符串中最频繁出现的分隔符,然后用该单个分隔符拆分。但是该方法必须有效,我想知道是否可以通过单个正则表达式来实现。问题主要是针对第一次出现的分隔符进行拆分 - 对于最常见的分隔符情况,几乎可以肯定需要提前计算出现次数。

更新:

该问题不要求同时按第一次出现或最常见的分隔符进行拆分-单独使用任何一种方法就足够了。我确实明白,如果没有初步确定分隔符,正则表达式不可能通过最常见的分隔符进行拆分,但我认为在没有事先准备的情况下,正则表达式和前瞻有可能通过第一次出现进行拆分。

【问题讨论】:

  • 没有正则表达式会找到最频繁的模式。您将不得不依赖其他语言手段。

标签: python regex split


【解决方案1】:

需要用字符串中第一个出现的分隔符或字符串中出现频率最高的分隔符进行分割。

因此,您可以首先找到所有分隔符并将它们保存在适当的容器中,然后找到最常见的第一个,然后根据它们拆分您的字符串。

现在要查找分隔符,您需要根据特定特征将它们与纯文本分开,例如,如果它们不是单词字符,并且为了保留它们,我们可以使用字典来保留相似的计数分隔符(在这种情况下 collections.Counter() 将完成这项工作)。

演示:

>>> s = "aaa#bbb*ccc#ddd*rkfh^ndjfh*dfehb*erjg-rh@fkej*rjh"
>>> delimiters = re.findall(r'\W', s)
>>> first = delimiters[0]
'#'
>>> Counter(delimiters)
Counter({'*': 5, '#': 2, '@': 1, '-': 1, '^': 1})
>>> 
>>> frequent = Counter(delimiters).most_common(1)[0][0]
'*'
>>> re.split(r'\{}|\{}'.format(first, frequent), s)
['aaa', 'bbb', 'ccc', 'ddd', 'rkfh^ndjfh', 'dfehb', 'erjg-rh@fkej', 'rjh']

请注意,如果您正在处理多个字符的分隔符,您可以使用re.escape() 来转义特殊的正则表达式字符(如*)。

【讨论】:

  • 这个问题实际上是为了避免寻找第一个也是最常见的分隔符的初步步骤。但是,如果无法避免这些步骤,这个答案为他们提供了一个很好的实现。
【解决方案2】:

我发现 string.count() 方法非常快,因为它是在 C 中实现的。任何避免 for 循环的东西通常会更快,即使您多次迭代字符串。这可能是最快的解决方案:

>>> s = 'aaa*bbb#ccc*ddd'
>>> a, b = s.count('*'), s.count('#')
>>> if a == b: a, b = -s.find('*'), -s.find('#')
... 
>>> s.split('*' if a > b else '#')
['aaa', 'bbb#ccc', 'ddd']

【讨论】:

  • .count() 和 .find() 比 .split() 快,如果 .split() 是最快的拆分方式.. 这应该很容易小于最佳速度的 5 倍解决方案。 (我猜不到 2 倍)
猜你喜欢
  • 2016-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
相关资源
最近更新 更多