使用正则表达式从单词列表中查找单词对

时间:2012-05-01 18:58:13

标签: python regex

我有一个单词列表,如:

l = """abc
dfg
hij
jih
gfd
cba
cbd
jip
gfe
jiw
cbw"""

我想从这个列表中找到成对的单词, 所以第一个词是:

.(.)(.)

第二个词是:

\2\1.

所以\ 1和\ 2引用第一个单词中的字符。

我能提出的最好的正则表达方式是:

re.findall('(^.(?P<A>.)(?P<B>.)$)(?=.*(^(?P=B)(?P=A).$))', l, re.DOTALL | re.MULTILINE)

但是这个搜索只返回一些对(因为findall只返回非重叠的结果......)。 然后我想到使用正向lookbehind断言,但它们只能用于固定长度的字符串...

有正确的方法吗?

1 个答案:

答案 0 :(得分:2)

我怀疑正则表达式是一种很好的方法(特别是在Python中,你不能简单地获得所有可能的匹配字符串的方法,就像在Perl中一样,所以你必须调用findall在你的字符串的所有前缀)。一个直截了当的选择是:

words = l.split()
pairs = set(frozenset((w1, w2)) for w1 in words for w2 in words 
                      if w1[1:] == w2[1::-1])

结果:

>>> map(tuple, pairs)
[('hij', 'jip'), 
 ('abc', 'cbd'), 
 ('dfg', 'gfd'), 
 ('dfg', 'gfe'), 
 ('jiw', 'hij'), 
 ('hij', 'jih'), 
 ('abc', 'cbw'), 
 ('abc', 'cba')]

你也可以通过在第一遍中保存字典中的单词前缀,然后在第二遍中建立关联来快速解决这个问题:

from collections import defaultdict

prefixes = defaultdict(list)
for w in words:
    prefixes[w[1::-1]].append(w) 
pairs = set(frozenset((w1, w2)) for w1 in words for w2 in prefixes[w1[1:]])

正则表达式引擎很难超越这种性能。