Перевірте, чи міститься елемент списку Python в іншій рядку


586

У мене є список:

my_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456']

і хочете шукати елементи, що містять рядок 'abc'. Як я можу це зробити?

if 'abc' in my_list:

Перевірить, чи 'abc'існує в списку, але він є частиною 'abc-123'та 'abc-456', 'abc'чи не існує сам по собі. Тож як я можу отримати всі предмети, які містять 'abc'?


19
Щоб перевірити протилежне (якщо одна рядок містить одну серед декількох рядків): stackoverflow.com/a/6531704/2436175
Антоніо

Якщо ліві частини записів унікальні, розгляньте можливість побудови дикту зі списку: Знайдіть запис у списку на основі часткового рядка
Георгій

Відповіді:


930

Якщо ви хочете перевірити лише наявність abcбудь-якого рядка в списку, ви можете спробувати

some_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456']
if any("abc" in s for s in some_list):
    # whatever

Якщо ви дійсно хочете отримати всі предмети, що містять abc, використовуйте

matching = [s for s in some_list if "abc" in s]

Я повинен перевірити, чи є один елемент у масиві з 6 елементів. Чи швидше робити 6 "якщо" чи це те саме?
Олів'є Понс

42
@OlivierPons, просто робиif myitem in myarray:
alldayremix

8
Ще один спосіб отримати всі рядки, що містять підрядку 'abc':filter(lambda element: 'abc' in element, some_list)
driftcatcher

2
@ p014k: використовуйте index()метод:try: return mylist.index(myitem); except ValueError: pass
Свен Марнах

1
@midkin: Я ні розумію, що саме ти намагався зробити, ні як це пішло не так. Вам, мабуть, пощастить, задавши нове запитання (за допомогою кнопки "Задати питання"), скопіювавши свій точний код, що б ви очікували від коду і що він насправді зробив. "Не працювало" абсолютно безглуздо, якщо ви не визначите, що означає "працює" в цьому контексті, але навіть тоді краще пояснити, що насправді сталося, а не говорити про те, що не відбулося.
Свен Марнах

104

Просто кидали це там: якщо вам трапиться необхідність відповідати проти більш ніж одного рядка, наприклад , abcі defви можете об'єднати два осягань наступним чином :

matchers = ['abc','def']
matching = [s for s in my_list if any(xs in s for xs in matchers)]

Вихід:

['abc-123', 'def-456', 'abc-456']

4
Це саме те, за що я гуглив .. Дякую!
N8TRO

2
Ви також можете використовувати {s for s in my_list for xs in matchers if xs in s}(зверніть увагу на фігурні дужки, щоб створити унікальний набір). Може бути легше читати, але може бути повільніше, якщо у більшості sзначень буде відповідність, оскільки ви anyефективно зупинитесь на першому матчі.
Маттіас Фріпп

82

Використовуйте filterдля отримання елементів, які є abc.

>>> lst = ['abc-123', 'def-456', 'ghi-789', 'abc-456']
>>> print filter(lambda x: 'abc' in x, lst)
['abc-123', 'abc-456']

Ви також можете використати розуміння списку.

>>> [x for x in lst if 'abc' in x]

До речі, не використовуйте слово listяк ім'я змінної, оскільки воно вже використовується для listтипу.


50

Якщо вам просто потрібно знати, чи є "abc" в одному з пунктів, це найкоротший шлях:

if 'abc' in str(my_list):

1
Це не вдасться, якби у вас був список ["abc1", "1abc2"], оскільки він знайде відповідність, оскільки рядок 'abc' буде у новоствореній рядку
cgseller

2
Так, це призначена поведінка ... правда, якщо будь-який із предметів містить "abc"
RogerS

7
Я не знаю, чому всі ці інші люди вирішують робити ці суперечливі лямбда-рішення, коли їм не потрібно! Приємна робота @RogerS
ntk4

1
Насправді те саме питання майже відповідає самому собі ... Я щойно до нього додав 3 листи.
RogerS

1
Це приємне рішення, але якщо ви хочете знайти елементи, які містять даний рядок, вам це не вдасться. Тут ви дізнаєтесь, чи містить будь-який із елементів рядок.
cslotty

18

Це досить давнє запитання, але я пропоную цю відповідь, тому що попередні відповіді не справляються з елементами у списку, які не є рядками (або якимось ітерабельним об’єктом). Такі пункти можуть спричинити збій всього розуміння списку за винятком.

Щоб витончено розібратися з такими елементами у списку, пропустивши елементи, які не можна повторити, скористайтеся наступним:

[el for el in lst if isinstance(el, collections.Iterable) and (st in el)]

потім із таким списком:

lst = [None, 'abc-123', 'def-456', 'ghi-789', 'abc-456', 123]
st = 'abc'

ви все одно отримаєте відповідні елементи ( ['abc-123', 'abc-456'])

Тест на ітерабельний може бути не найкращим. Отримав це звідси: На Python, як я можу визначити, чи є об'єкт ітерабельним?


Не було [el for el in lst if el and (st in el)]б більше сенсу в даному прикладі?
Гордо

@tinix Я не знаю, що буде обробляти неітерабельні об'єкти витончено, чи не так?
Роберт Мюїл

"наведений приклад" my_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456'] не потрібно надто ускладнювати це.
Гордо

1
Так абсолютно - прийнята відповідь цілком підходить, і моя пропозиція є складнішою, тому сміливо ігноруйте її - я просто запропонував у випадку, якщо у когось виникли ті самі проблеми, що і у мене: елементи, які не можна повторити в таких списках, є реальною можливістю незважаючи на відсутність у наведеному прикладі.
Роберт Мюїл


10
for item in my_list:
    if item.find("abc") != -1:
        print item

3
Якщо ви збираєтесь використовувати цей підхід, я вважаю, що це більш ідіоматично робити, if 'abc' in itemніж використовувати item.find('abc') == -1.
Wyatt Baldwin



3

Я новачок у Python. Я отримав код, який працює нижче, і полегшив його розуміння:

my_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456']
for str in my_list:
    if 'abc' in str:
       print(str)

0
my_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456']

for item in my_list:
    if (item.find('abc')) != -1:
        print ('Found at ', item)

0
mylist=['abc','def','ghi','abc']

pattern=re.compile(r'abc') 

pattern.findall(mylist)

У Python3.6 це дає помилку: TypeError: очікуваний рядок або
байтовий

1
@AimForClarity Так. re.findall в python3.6 очікує рядок. Альтернативою було б перетворення списку в рядок import re mylist=['abc','def','ghi','abcff'] my_list_string=''.join(mylist) string_to_find="abc" res=re.findall(string_to_find,my_list_string) print(res)
arun_munagala

1
Вибачте за неправильне форматування. Чомусь не вдалося зробити належні розриви рядків.
arun_munagala

0

Я здійснив пошук, який вимагає від вас ввести певне значення, тоді воно буде шукати значення зі списку, який містить ваш вхід:

my_list = ['abc-123',
        'def-456',
        'ghi-789',
        'abc-456'
        ]

imp = raw_input('Search item: ')

for items in my_list:
    val = items
    if any(imp in val for items in my_list):
        print(items)

Спробуйте шукати "abc".



0

Мені потрібні були такі індекси списку, які відповідають відповідності:

lst=['abc-123', 'def-456', 'ghi-789', 'abc-456']

[n for n, x in enumerate(lst) if 'abc' in x]

вихід

[0, 3]

-1

Питання: Надайте інформацію аб

    a = ['abc-123', 'def-456', 'ghi-789', 'abc-456']


    aa = [ string for string in a if  "abc" in string]
    print(aa)

Output =>  ['abc-123', 'abc-456']

-2

Наскільки мені відомо, твердження «за» завжди вимагатиме часу.

Коли довжина списку зростає, час виконання також зростатиме.

Я думаю, що пошук підрядки в рядку з оператором 'є' трохи швидше.

In [1]: t = ["abc_%s" % number for number in range(10000)]

In [2]: %timeit any("9999" in string for string in t)
1000 loops, best of 3: 420 µs per loop

In [3]: %timeit "9999" in ",".join(t)
10000 loops, best of 3: 103 µs per loop

Але я погоджуюся, що anyтвердження є більш читабельним.

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