Перевірте, чи існує кілька рядків в іншій рядку


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"

Цей код не працює, це просто показати, чого я хочу досягти.


5
Я здивований, що немає (поки що) жодних відповідей у ​​порівнянні зі складеним регулярним виразом з точки зору perf, особливо порівняно з розміром рядка та кількістю «голок» для пошуку.
Пт

3
@Pat Я не здивований. Питання не в продуктивності. Сьогодні більшість програмістів більше піклуються про те, щоб зробити це і читати. Питання про виконання дійсне, але питання інше.
guettli

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
будь-який () приймає ітерабельний. Я не впевнений, яку версію Python ви використовуєте, але в 2.6 вам потрібно буде поставити [] навколо свого аргументу до будь-якого (). будь-який ([x in str for x in a]), так що розуміння повертає ітерабельний. Але, можливо, пізніші версії Python вже роблять це.
випромінювач

7
@Mark Byers: Вибачте за пізній коментар, але чи є спосіб надрукувати знайдений рядок? Як би ти це зробив. Дякую.
Шанкар Кумар

3
Не впевнений, що я розумію, якщо a - це список, а str - це річ, з якою потрібно відповідати, що таке x? Python newbie ftw. :)
червоний

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)

будь ласка, додайте приклад і для останнього матчу
Олег Кокорін

@OlegKokorin: Він створює список відповідних рядків у тому самому порядку, коли він їх знаходить, але він зберігає лише перший, якщо два однакові.
zondo

Використання атрибуту OrderedDict, ймовірно, більш ефективне, ніж список. Дивіться цю відповідь на тему "Видалення дублікатів у списках"
wjandrea

44

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


Чи може Aho-Corasick також знайти підрядки замість префіксів?
RetroCode

1
Деякі бібліотеки пітона 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))


1
Це працює для даного випадку використання питання. Якщо пошук, який ви шукаєте, (або *це не вдається, оскільки потрібно виконати цитування синтаксису регулярних виразів.
guettli

2
Ви можете уникнути цього, якщо це необхідно '|'.join(map(re.escape, strings_to_match)). Ви, мабуть, re.compile('|'.join(...))також можете.
Artyer

12

Потрібно перебрати елементи а.

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
Так, я знав, як це зробити, але порівняно з відповіддю Маркса, це жахливий код.
jahmax

10
Тільки якщо ви розумієте код Марка. Проблема, яку ви мали, полягає в тому, що ви не вивчали елементи свого масиву. Існує багато хитромудрих, пітонічних способів досягти того, що ви хочете, що приховувало б суть того, що було не так у вашому коді.
Seamus Campbell

9
Це може бути "жахливий код", але це саме те, що робить будь-який () . Крім того, це дає вам фактичну відповідність рядка, тоді як будь-який () просто говорить вам про збіг.
alldayremix

4

jbernadas вже згадував алгоритм Ахо-Корасика з метою зменшення складності.

Ось один із способів його використання в Python:

  1. Завантажте aho_corasick.py звідси

  2. Помістіть його в той самий каталог, що і ваш основний файл Python, і дайте ім’я aho_corasick.py

  3. Спробуйте алгоритм із наступним кодом:

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

Зауважте, що пошук залежить від регістру


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"

1

Це залежить від контексту , припустимо , якщо ви хочете , щоб перевірити одного Літерал як (будь одне слово а, е, ж, .. і т.д.) в досить

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

якщо ви хочете перевірити будь-який символ серед original_word: скористайтеся

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

якщо ви хочете, щоб весь вхід, який ви хочете, в цьому 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')

вихідний приклад зображення


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)));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.