Проверьте, существует ли несколько строк в другой строке

378

Как я могу проверить, существует ли какая-либо из строк в массиве в другой строке?

Подобно:

a = ['a', 'b', 'c']
str = "a123"
if a in str:
  print "some of the strings found in str"
else:
  print "no strings found in str"

Этот код не работает, он просто показывает, чего я хочу достичь.

jahmax
источник
5
Я удивлен, что нет (пока) никаких ответов по сравнению с скомпилированным регулярным выражением в терминах perf, особенно по сравнению с размером строки и количеством «игл» для поиска.
Пэт
3
@ Пэт, я не удивлен. Вопрос не в производительности. Сегодня большинство программистов больше заботятся о том, чтобы сделать это и удобочитаемостью. Вопрос производительности действителен, но другой вопрос.
Геттли
13
Использование str в качестве переменной сбивает с толку и может привести к неожиданному поведению, поскольку это зарезервированное слово; см ссылку .
Умный парень
Кроме того, регулярное выражение [abc]работает отлично и будет быстрее, если нужно протестировать более двух кандидатов. Но если строки являются произвольными, и вы не знаете их заранее, чтобы построить регулярное выражение, вам придется использовать any(x in str for x in a)подход.
SMCI
@CleverGuy Вы правы, хотя это не зарезервированное слово, иначе вы не сможете его назначить. Это встроенный.
wjandrea

Ответы:

717

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

a_string = "A string is more than its parts!"
matches = ["more", "wholesome", "milk"]

if any(x in a_string for x in matches):

Аналогично, чтобы проверить, все ли строки из списка найдены, используйте allвместо any.

Марк Байерс
источник
11
any () занимает многократное повторение. Я не уверен, какую версию Python вы используете, но в 2.6 вам нужно будет поставить [] вокруг аргумента any (). любой ([x в str для x в a]), так что понимание возвращает итерируемое. Но, возможно, более поздние версии Python уже делают это.
emispowder
7
@Mark Byers: Извините за поздний комментарий, но есть ли способ напечатать найденную строку? Как бы ты это сделал? Спасибо.
Шанкар Кумар
3
Не уверен, что понимаю, если a - это список, а str - это то, с чем нужно сравнивать, что такое x? Питон новичок :)
красный
2
@red: вы можете читать for x in aкак «для каждого элемента в списке». Поскольку aпредставляет собой список строк и xявляется элементом этого списка, xпредставляет собой строку (одну из 'a', 'b', 'c' в исходном примере)
пользователь
6
@emispowder Это прекрасно работает для меня как есть в Python 2.6.9.
MPlanchard
67

any()безусловно, лучший подход, если все, что вы хотите, это Trueили False, но если вы хотите точно знать, какие строки / строки соответствуют, вы можете использовать несколько вещей.

Если вы хотите первое совпадение ( Falseпо умолчанию):

match = next((x for x in a if x in str), False)

Если вы хотите получить все совпадения (включая дубликаты):

matches = [x for x in a if x in str]

Если вы хотите получить все неповторяющиеся совпадения (без учета порядка):

matches = {x for x in a if x in str}

Если вы хотите получить все неповторяющиеся совпадения в правильном порядке:

matches = []
for x in a:
    if x in str and x not in matches:
        matches.append(x)
zondo
источник
пожалуйста, добавьте пример и для последнего матча
Олег Кокорин
@OlegKokorin: создает список совпадающих строк в том же порядке, в котором находит их, но сохраняет только первую, если две одинаковые.
Зондо
Использование, OrderedDictвероятно, более производительно, чем список. Смотрите этот ответ на "Удаление дубликатов в списках"
wjandrea
44

Вы должны быть осторожны, если строки aили strстановятся длиннее. Простые решения берут O (S * (A ^ 2)), где S- длина, strа A - сумма длин всех строк в a. Для более быстрого решения взгляните на алгоритм Aho-Corasick для сопоставления строк, который выполняется за линейное время O (S + A).

jbernadas
источник
может ли Aho-Corasick также найти подстроки вместо префиксов?
RetroCode 26.09.16
1
Некоторые библиотеки Python Aho-Corasick находятся здесь и здесь
vorpal
23

Просто чтобы добавить немного разнообразия с regex:

import re

if any(re.findall(r'a|b|c', str, re.IGNORECASE)):
    print 'possible matches thanks to regex'
else:
    print 'no matches'

или если ваш список слишком длинный - any(re.findall(r'|'.join(a), str, re.IGNORECASE))

Шанкар АРУЛ - jupyterdata.com
источник
1
Это работает для данного варианта использования вопроса. Если вы ищете (или *это не удается, так как цитирование для синтаксиса регулярных выражений должно быть сделано.
Гетли
2
Вы можете избежать этого при необходимости с '|'.join(map(re.escape, strings_to_match)). Вы, наверное, re.compile('|'.join(...))тоже.
Artyer
12

Вам нужно перебрать элементы a.

a = ['a', 'b', 'c']
str = "a123"
found_a_string = False
for item in a:    
    if item in str:
        found_a_string = True

if found_a_string:
    print "found a match"
else:
    print "no match found"
Симус Кэмпбелл
источник
2
Да, я знал, как это сделать, но по сравнению с ответом Маркса, это ужасный код.
Джахмакс
11
Только если вы понимаете код Марка. Проблема в том, что вы не проверяли элементы своего массива. Есть много кратких, питонских способов выполнить то, что вы хотите, что бы скрыть суть того, что было не так с вашим кодом.
Симус Кэмпбелл
10
Это может быть «ужасный код», но это именно то, что делает any () . Кроме того, это дает фактическую строку, которая соответствует, тогда как any () просто говорит вам, что есть совпадение.
alldayremix
4

Jbernadas уже упоминал алгоритм Aho-Corasick , чтобы уменьшить сложность.

Вот один из способов использовать его в Python:

  1. Загрузите aho_corasick.py отсюда

  2. Поместите его в тот же каталог, что и ваш основной файл Python, и назовите его aho_corasick.py

  3. Попробуйте alrorithm с помощью следующего кода:

    from aho_corasick import aho_corasick #(string, keywords)
    
    print(aho_corasick(string, ["keyword1", "keyword2"]))

Обратите внимание, что поиск чувствителен к регистру

Domi W
источник
3
a = ['a', 'b', 'c']
str =  "a123"

a_match = [True for match in a if match in str]

if True in a_match:
  print "some of the strings found in str"
else:
  print "no strings found in str"
mluebke
источник
1

Это зависит от контекста , предположим , если вы хотите , чтобы проверить одного Литерал как (любое одно слово а, е, ж, .. и т.д.) в достаточно

original_word ="hackerearcth"
for 'h' in original_word:
      print("YES")

если вы хотите проверить какой-либо символ из оригинального слова: используйте

if any(your_required in yourinput for your_required in original_word ):

если вы хотите, чтобы все входные данные были в этом оригинальном слове, используйте все простые

original_word = ['h', 'a', 'c', 'k', 'e', 'r', 'e', 'a', 'r', 't', 'h']
yourinput = str(input()).lower()
if all(requested_word in yourinput for requested_word in original_word):
    print("yes")
Тринад Койя
источник
Какой будет твой вход? Я могу распознать две вещи: предложение, где я ищу что-то. Массив слов, которые я ищу. Но вы описываете три переменные, а я не могу понять, какая третья.
mayid
1

Еще немного информации о том, как получить все элементы списка, доступные в String.

a = ['a', 'b', 'c']
str = "a123" 
list(filter(lambda x:  x in str, a))
Нилеш Бирари
источник
1

Удивительно быстрый подход заключается в использовании set:

a = ['a', 'b', 'c']
str = "a123"
if set(a) & set(str):
    print("some of the strings found in str")
else:
    print("no strings found in str")

Это работает, если aне содержит многосимвольных значений (в этом случае используйте anyкак указано выше ). Если это так, то проще указать aв виде строки: a = 'abc'.

Берислав Лопач
источник
0
flog = open('test.txt', 'r')
flogLines = flog.readlines()
strlist = ['SUCCESS', 'Done','SUCCESSFUL']
res = False
for line in flogLines:
     for fstr in strlist:
         if line.find(fstr) != -1:
            print('found') 
            res = True


if res:
    print('res true')
else: 
    print('res false')

пример вывода изображения

LeftSpace
источник
0

Я бы использовал такую ​​функцию для скорости:

def check_string(string, substring_list):
    for substring in substring_list:
        if substring in string:
            return True
    return False
Иван Михайлов
источник
0
data = "firstName and favoriteFood"
mandatory_fields = ['firstName', 'lastName', 'age']


# for each
for field in mandatory_fields:
    if field not in data:
        print("Error, missing req field {0}".format(field));

# still fine, multiple if statements
if ('firstName' not in data or 
    'lastName' not in data or
    'age' not in data):
    print("Error, missing a req field");

# not very readable, list comprehension
missing_fields = [x for x in mandatory_fields if x not in data]
if (len(missing_fields)>0):
    print("Error, missing fields {0}".format(", ".join(missing_fields)));
Роберт I
источник