2012-05-01 3 views
4

у меня есть список слов, таких как:Использование 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, но их можно использовать только со строками фиксированной длины ...

Есть ли способ для этого с регулярным выражением?

+0

Можете ли вы объяснить взаимосвязь между парами слов в словах, а не только с примером? Я думаю, вы, возможно, потеряли определенную точность. Являются ли слова всегда ровно 3 буквы длинными, как показано на рисунке? –

+0

В ваших данных образца 'abc' может быть сопряжен с' cba', 'cbd' или' cbw'. У вас есть предпочтения? Или вы хотите получить все из них? –

+0

@Alan: Очевидно, он хочет получить все из них, иначе подход с регулярным выражением будет работать. –

ответ

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:]]) 

Эксплуатационные характеристики этого будут трудно преодолеть с помощью механизма регулярных выражений.

+0

Предполагая, что у меня очень длинный список слов, вы не используете регулярное выражение (если это возможно ...) быстрее, чем использование списка, которое проходит через список дважды? – ItaiS

+0

@ItaiS: Я очень сомневаюсь, что решение словаря поиска - O (n). Вид NFA я имею в виду, что механизм регулярного выражения создавал бы квадратное время выполнения, потому что он ничего не знает о семантике проблемы. Вы сравнили? –

Смежные вопросы