所以我有多个不同长度的列表。我正在尝试使用正则表达式在语料库中搜索包含这些列表中项目的任意组合的字符串。我不知道该怎么做,并且一直在寻找解决方案。如果有人可以启发我一种技术,或者向我指出一些文档,那也是可以接受的答案。
示例
l1 = ["two","three",...,"twenty"]
l2 = ["cats","dogs","fish",...]
my_corpus = """
I have three cats and two dogs, but I have no fish.
I don't care too much about being correct so matching
the phrase dogs four is acceptable as well.
"""
理想情况下,我想在此处匹配 “三只猫”、“两只狗” 和 “四只狗”。
请务必注意,实际列表的数量各不相同,而且顺序并不重要。但是肯定有太多可能的排列来硬编码。如果我什至编写一个脚本来创建带有 OR 字符串的正则表达式,该字符串最终会太大(可能超过 100 万个字符)。
编辑笔记
- 对于任意数量的列表,这必须是可能的。如前所述,由于这些列表的大小,这里不可能进行硬编码。实际上我使用了 6 个列表,大小分别为 2,10,10,100,1000,10000。
- 这必须是正则表达式的一部分。这是一个子问题,它是已经在正则表达式中完成的复杂解析尝试的一部分。让预先存在的正则表达式为
r'abc'我希望能够将其转换为 r'a(?:b|solution)c',其中 a、b 和 c 已经是完整的正则表达式。- 它必须连续匹配任意数量的这些单词
如果还有其他问题,请告诉我。
请您参考如下方法:
它必须是正则表达式吗?
为什么不直接遍历单词并检查列表中是否有 N 个相邻的单词?
import re
l1 = ["two","three","four","twenty"]
l2 = ["cats","dogs","fish"]
my_corpus = """
I have three cats and two dogs, but I have no fish.
I don't care too much about being correct so matching
the phrase dogs four is acceptable as well.
"""
non_alpha = re.compile('[^a-zA-Z]')
words = [non_alpha.sub('',w) for w in my_corpus.split()]
sets = map(set,[l1,l2])
N = len(sets)
for i in range(len(words)-N):
ws = words[i:i+N]
# each word is in at least one set
all_words = all(any(w in s for s in sets) for w in ws)
# each set has at least one word
all_sets = all(any(w in s for w in ws) for s in sets)
# conditions broken into two for readability, but maybe should be used
# inline for short circuiting, only important if number of sets is large
if all_words and all_sets:
print ' '.join(ws)
输出:
three cats
two dogs
dogs four
另外,正如@tobias_k 所评论的,使用集合而不是列表会加快速度
