【问题标题】:FInd repeated pattern between strings查找字符串之间的重复模式
【发布时间】:2015-01-27 06:38:36
【问题描述】:

我有以下列表:someList = ['blablahihix', 'somethinghihi'],我想返回一个列表,其中包含列表的两个元素之间的重复模式(在本例中为“hihi”)。

这就是我正在做的事情:

p, r = re.compile(r'(.+?)\1+'), []
for i in strList:
    r.extend(p.findall(i) or [i])

当我print r 时,它给了我['bla', 'hi', 'hi']。我想要的只是['hihi']。我不希望返回“blabla”,因为列表的第二个元素中没有“blabla”。

我错过了什么?

【问题讨论】:

  • 你的 somdict 字典还是列表?
  • 你为什么不期望hi,或hih,或ihi,或h,或i是重复模式?在任意两个中等长度的字符串之间,存在可能的共享模式爆炸。您可能需要考虑是否可以替代您所问的问题。也许您真正想要的是两者中出现的最大子字符串。
  • 对不起,我的意思是列表而不是字典。
  • 我想要的是 someList 进行迭代,以便返回“hihi”(这是两个元素之间的重复模式)
  • 如果“重复”是指“存在于两个字符串中”,那么hihi 不是唯一的“重复模式”。 hihi 的任何子字符串(例如 ihi)也会重复。如果是这样的话,那么我猜你真正想要的是一组最大的重复模式。但这仍然可能不是您所期望的。例如,如果你的两个字符串是“axbhihicd”和“efhihixg”,那么“hihi”是最大重复模式,“x”也是。

标签: python regex list


【解决方案1】:

使用set操作得到匹配组的交集:

>>> strList = ['blablahihix', 'somethinghihi']
>>> p = re.compile(r'(.+?)\1+')

>>> [set(p.findall(i)) for i in strList]
[{'bla', 'hi'}, {'hi'}]

>>> # from functools import reduce  # In Python 3.x
>>> reduce(lambda a, b: a & b, (set(p.findall(i)) for i in strList))
{'hi'}

使用set & set or set.intersection 获取两个匹配项中都出现的共同部分。


您需要修改模式或使用re.finditer,因为re.findall根据是否使用捕获组返回的方式;如果模式中存在一个或多个组,则返回组列表而不是整个匹配字符串的列表。

>>> import re
>>>
>>> strList = ['blablahihix', 'somethinghihi']
>>> p = re.compile(r'(.+?)\1+')
>>> reduce(lambda a, b: a & b,
           (set(m.group() for m in p.finditer(i)) for i in strList))
{'hihi'}

更新

按照 georg 的建议,您可以使用set.intersection(*...);不需要使用reduce

>>> set.intersection(*(set(m.group() for m in p.finditer(i)) for i in strList))
{'hihi'}

【讨论】:

  • 我猜他们的措辞不正确,他们实际上是在寻找 LCS,而不是“重复”字符串。
  • @georg,我的想法不同,因为 OP 使用了 (.+?)\1+ 模式;要求子字符串应该是重复的。
  • 啊,好的,我明白了。我会使用 set.intersection(*... 而不是 reduce ;)
  • @georg,谢谢你的建议。我加了。
猜你喜欢
  • 2015-12-01
  • 2017-07-07
  • 2020-05-28
  • 2011-03-23
  • 2014-03-24
  • 2015-05-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多