2015-11-19 2 views
1

Я получаю ложные срабатывания в python для следующего примера. Я пытаюсь найти, существует ли ключевое слово в строке. Проблема в том, что в строке есть слова, связанные обычно символом подчеркивания или дефиса, поэтому я хочу только получить положительный результат, если ключевое слово существует, если не словом. Он может быть окружен дефисом, подчеркиванием или чем-либо, что не является письмом, которое следует считать истинным результатом. Обычно он должен быть окружен подчеркиванием или дефис. Это не чувствительно к регистру.Python Regex - найти шаблон строки в слове

test_list = ['server_test', 'server_dev', 'server_uat', 'server_dr', 'server-dr-NA', 'server-DR', 'dress_prod', 'testosterone','uatae','devacurl', 'dev_server'] 

Результат должен вывести этот список True/False

[True, True, True, True, True, True, False, False, False, False, True] 

Реализация:

key_words = ['uat','dr','test','qa','dev'] 
for name in test_list: 
    if any(x in name.lower() for x in key_words): 
     print('True') 
    else: 
     print('False') 

Результаты:

True 
True 
True 
True 
True 
True 
True 
True 
True 
True 

Является ли есть лучший способ сделать это в питон?

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

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

ответ

1

Использование негативного lookge на основе regex.

>>> test_list = ['server_test', 'server_dev', 'server_uat', 'server_dr', 'server-dr-NA', 'server-DR', 'dress_prod', 'testosterone','uatae','devacurl', 'dev_server'] 
>>> key_words = ['uat','dr','test','qa','dev'] 
>>> [True if re.search(r'(?i)(?<![a-z])(?:' + '|'.join(key_words) + ')(?![a-z])', i) else False for i in test_list] 
[True, True, True, True, True, True, False, False, False, False, True] 
>>> 
0

Другим методом является использование \b для определения границ слов. К сожалению, _ считается символом слова, поэтому нам необходимо определить \bили _.

Не так сложно или эффективно, как решение Avinash, но, возможно, более читаемо.

import re 

test_list = ['server_test', 'server_dev', 'server_uat', 'server_dr', 
      'server-dr-NA', 'server-DR', 'dress_prod', 'testosterone', 
      'uatae', 'devacurl', 'dev_server'] 

key_words = ['uat','dr','test','qa','dev'] 

for name in test_list: 
    for kw in key_words: 
     regex = r'(\b|_)'+kw+r'(\b|_)' 
     if re.search(regex, name, re.IGNORECASE): 
      print('True') 
      break # exit "for kw" loop 
    else: # only executed if "for kw" loop exits via exhaustion, not via break 
     print('False') 
0

Я думаю, что эта модель будет легко понять и изменить:

import re 

pattern = r'.*(^|[^a-z])({names})([^a-z]|$).*'.format(names='|'.join(key_words)) 

# .*(^|[^a-z])(uat|dr|test|qa|dev)([^a-z]|$).* 

for name in test_list: 
    print(bool(re.search(pattern, name, re.IGNORECASE))) 
0
import re 

key_words = ['uat','dr','test','qa','dev'] 
test_list = ['server_test', 'server_dev', 'server_uat', 'server_dr', 'server-dr-NA', 
      'server-DR', 'dress_prod', 'testosterone','uatae','devacurl', 'dev_server'] 



def check(word): 
    parts = re.split('[^a-z]', word.lower()) 
    return any(part in key_words for part in parts) 

print([check(item) for item in test_list]) 
2

Дано:

>>> test_list = ['server_test', 'server_dev', 'server_uat', 'server_dr', 'server-dr-NA', 'server-DR', 'dress_prod', 'testosterone','uatae','devacurl', 'dev_server'] 
>>> key_words = ['uat','dr','test','qa','dev'] 

Вы можете использовать re.split и any:

>>> [any(word.lower() in key_words for word in re.split(r'[^a-zA-Z]', s)) 
...  for s in test_list] 
[True, True, True, True, True, True, False, False, False, False, True] 

То же, что и ваша цель:

>>> tgt=[True, True, True, True, True, True, False, False, False, False, True] 
>>> [any(word.lower() in key_words for word in re.split(r'[^a-zA-Z]', s)) 
...  for s in test_list]==tgt 
True 
Смежные вопросы