使用正则表达式在Python中查找字符串的三个部分

使用正则表达式在Python中查找字符串的三个部分,python,regex,tokenize,Python,Regex,Tokenize,我有三个字符串,它是三个组件的串联: 列表1中的一个单词(包括空字符串) 清单2中的一个单词 列表3中的一个单词(包括空字符串) 列表1、2和3最多可包含5000个元素。一个列表中的元素不在其他列表中(空字符串除外)。然而,有些词可以是其他词的一部分 我正在寻找一种有效的方法来找到这三个组成部分。现在我正在做以下工作: for word in list2: if word in long_word: try: [bef, aft] = long_

我有三个字符串,它是三个组件的串联:

  • 列表1中的一个单词(包括空字符串)
  • 清单2中的一个单词
  • 列表3中的一个单词(包括空字符串)
列表1、2和3最多可包含5000个元素。一个列表中的元素不在其他列表中(空字符串除外)。然而,有些词可以是其他词的一部分

我正在寻找一种有效的方法来找到这三个组成部分。现在我正在做以下工作:

for word in list2:
    if word in long_word:
        try:
           [bef, aft] = long_word.split(word)
        except ValueError: # too many values to unpack
           continue
        if bef in list1 and aft in list3:
           print('Found: {}, {}, {}'.format(bef, word, aft))
           break
else:
    print('Not found')
我想知道是否有更好的办法。我想在正则表达式中使用管道。但是,正如我所得到的,替代方案的数量似乎太多了:OverflowerError:正则表达式代码大小超出了限制

谢谢

更新 我尝试了建议解决方案的修改版本:

def fj(long_word, list1, list2, list3):
    for x in filter(long_word.startswith, list1):
        for y in filter(long_word[len(x):].startswith, list2):
            z = long_word[len(x)+len(y):]
            if z in list3:
                yield x, y, z

def sid(long_word, list1, list2, list3):
    for w1 in list1:
        if not long_word.startswith(w1):
            continue
        cut1 = long_word[len(w1):]
        for w2 in list2:
           if not cut1.startswith(w2):
               continue
           cut2 = cut1[len(w2):]
           for w3 in list3:
               if cut2 == w3:
                   yield w1, w2, w3

def my(long_word, list1, list2, list3):
    for word in list2:
        if word in long_word:
            try:
               [bef, aft] = long_word.split(word)
            except ValueError: # too many values to unpack
               continue
            if bef in list1 and aft in list3:
               yield bef, word, aft
这是我使用8000个元素重复10000次的列表得到的计时(标准化)结果,每次从每个列表中随机选取一个单词来生成长单词

  • my:1.0
  • sid:4.5
  • 福建:2.7

我真的很惊讶,因为我认为fj的方法将是最快的。

正则表达式可能不太适合这里,我可能会这样做:

for x in filter(long_word.startswith, list1):
    for y in filter(long_word[len(x):].startswith, list2):
        z = long_word[len(x)+len(y):]
        if z in list3:
            print('Found: {}, {}, {}'.format(x, y, z))
            break
    else:
        continue
    break
else:
    print('Not found')

一个简单的算法是运行3个循环:

for w1 in list1:
    p1=re.match(w1,s)
    if p1==None:
        continue
    for w2 in list2:
       p2=re.match(w2,s[p1.pos+len(w1):])  
       if p2==None:
         continue
       for w3 in list3:
           p3=re.match(w3,s[p2.pos+len(w2):])  

我认为您仍然会遇到list1的子字符串作为list2的一部分的问题。F.J的方法可能更好。

我的回答并不能完全回答你的问题,但它确实提醒了我们在这个问题中要处理的问题

列表1、2和3最多可包含5000个元素

这意味着列表1、2和3是相同的。从这里开始,我将列表1表示为A,列表2表示为B,列表3表示为C

  • 列表1中的一个单词(包括空字符串)
  • 清单2中的一个单词
  • 列表3中的一个单词(包括空字符串)
因此,空字符串(lambda)位于A和C中

您有一个字符串w,它可以用

w=abc

其中a是a中的字符串,b是b中的字符串,c是c中的字符串

您试图做的是将w拆分为子字符串a、b和c

由于a可以为空,c可以为空,因此您有以下几种可能性:

  • w=abc
  • w=ab
  • w=bc
  • w=b
  • 首先,让我们消除#4的琐碎场景


    当我仔细考虑这一点时,我会提供更多信息。

    您将性能与不完整的解决方案进行比较(
    除了ValueError:
    将继续非常快,但会给您错误的结果-特别是如果列表2中有大量重复的单词,列表中或列表之间没有重复的单词。此外,在我的测试脚本中,我比较了所有三个脚本的结果,我总是得到相同的结果。那么你应该
    提高
    ,而不是
    继续
    。。。或者至少打印一些调试消息-例如,您可以在列表1中显示“aaa”,在列表2中显示“aa”-即使您的测试结果是正确的,您的脚本也可能会在可能匹配但数据不匹配的情况下过早失败(当然,更正后可能会更快),谢谢您的评论!。这是一个很好的观点。我在你的作品中找到了一个更快的版本。请参阅我对该问题的更新。
    if w in B:
      a = ""
      b = w
      c = ""
      print('Found: {}, {}, {}'.format(a, b, c))