Sprawdź, czy element listy Python zawiera łańcuch wewnątrz innego łańcucha


586

Mam listę:

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

i chcesz wyszukać elementy zawierające ciąg 'abc'. Jak mogę to zrobić?

if 'abc' in my_list:

by sprawdzić, czy 'abc'istnieje na liście, ale to jest częścią 'abc-123'i 'abc-456', 'abc'nie istnieje na własną rękę. Jak mogę zdobyć wszystkie przedmioty, które zawierają 'abc'?


19
Aby sprawdzić odwrotnie (jeśli jeden ciąg zawiera jeden spośród wielu ciągów): stackoverflow.com/a/6531704/2436175
Antonio

Jeśli lewe części wpisów są unikalne, rozważ utworzenie słownika z listy: Znajdź wpis na liście na podstawie częściowego ciągu znaków
Georgy

Odpowiedzi:


930

Jeśli chcesz tylko sprawdzić obecność abcdowolnego ciągu na liście, możesz spróbować

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

Jeśli naprawdę chcesz uzyskać wszystkie elementy zawierające abc, użyj

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

Muszę sprawdzić, czy jeden element jest w tablicy 6 elementów. Czy szybciej jest zrobić 6 „jeśli”, czy jest to to samo?
Olivier Pons,

41
@OlivierPons, po prostu zróbif myitem in myarray:
alldayremix

8
Innym sposobem uzyskania wszystkich ciągów zawierających podciąg „abc”:filter(lambda element: 'abc' in element, some_list)
driftcatcher

2
@ p014k: użyj index()metody:try: return mylist.index(myitem); except ValueError: pass
Sven Marnach

1
@midkin: Nie rozumiem, co dokładnie próbowałeś zrobić, ani tego, jak poszło nie tak. Prawdopodobnie będziesz mieć więcej szczęścia, zadając nowe pytanie (za pomocą przycisku „Zadaj pytanie”), kopiując dokładny kod, czego oczekiwałbyś od kodu i co faktycznie zrobił. „Nie działało” jest całkowicie bez znaczenia, chyba że zdefiniujesz, co w tym kontekście oznacza „działa”, ale nawet wtedy lepiej jest wyjaśnić, co się właściwie stało, niż powiedzieć, co się nie udało.
Sven Marnach,

104

Po prostu to wyrzucamy: jeśli na przykład musisz dopasować więcej niż jeden ciąg abc i defmożesz połączyć dwa wyrażenia w następujący sposób:

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

Wynik:

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

4
Właśnie po to szukałem google. Dzięki!
N8TRO,

2
Możesz także użyć {s for s in my_list for xs in matchers if xs in s}(zwróć uwagę na nawiasy klamrowe, aby stworzyć unikalny zestaw). Może być łatwiejszy do odczytania, ale może być wolniejszy, jeśli większość swartości będzie pasować, ponieważ anyskutecznie zatrzyma się przy pierwszym dopasowaniu.
Matthias Fripp

82

Użyj, filteraby dostać się do elementów, które mają abc.

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

Możesz także użyć listy.

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

Nawiasem mówiąc, nie używaj tego słowa listjako nazwy zmiennej, ponieważ jest ono już używane dla tego listtypu.


50

Jeśli potrzebujesz tylko wiedzieć, czy „abc” jest w jednym z elementów, jest to najkrótsza droga:

if 'abc' in str(my_list):

1
Nie udałoby się to, gdybyś miał listę [„abc1”, „1abc2”], ponieważ znalazłby dopasowanie, ponieważ ciąg „abc” byłby w nowo utworzonym ciągu
cgseller

2
Tak, jest to zamierzone zachowanie ... prawda, jeśli którykolwiek z elementów zawiera „abc”
RogerS

7
Nie wiem, dlaczego wszyscy ci inni decydują się na zawiłe rozwiązania lambda, kiedy nie muszą! Dobra robota @RogerS
ntk4

1
Właściwie to samo pytanie prawie samo odpowiada ... Właśnie dodałem do niego 3 litery.
RogerS

1
To miłe rozwiązanie, ale jeśli chcesz znaleźć elementy zawierające podany ciąg, nie odniesiesz sukcesu. Tutaj dowiesz się, czy któryś z elementów zawiera ciąg.
cslotty

18

To dość stare pytanie, ale oferuję tę odpowiedź, ponieważ poprzednie odpowiedzi nie dotyczą elementów na liście, które nie są łańcuchami (lub jakimś obiektem iterowalnym). Takie pozycje spowodowałyby niepowodzenie pełnego zrozumienia listy z wyjątkiem.

Aby z wdziękiem radzić sobie z takimi elementami na liście, pomijając elementy, które nie są iterowalne, użyj następujących czynności:

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

następnie z taką listą:

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

nadal otrzymasz pasujące przedmioty (['abc-123', 'abc-456'] )

Test iterowalności może nie być najlepszy. Mam to stąd: w Pythonie, jak ustalić, czy obiekt jest iterowalny?


Czy [el for el in lst if el and (st in el)]w podanym przykładzie nie miałoby to większego sensu?
Gordo,

@tinix Nie zrobię tego z wdziękiem radzi sobie z obiektami, które nie mogą być iterowalne, prawda?
Robert Muil

„podany przykład” my_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456'] nie musi go nadmiernie komplikować.
Gordo,

1
Tak, absolutnie - zaakceptowana odpowiedź jest całkowicie odpowiednia, a moja sugestia jest bardziej skomplikowana, więc możesz ją zignorować - po prostu zaoferowałem na wypadek, gdyby ktoś miał taki sam problem jak ja: przedmioty, które nie są iterowalne na takich listach, są realną możliwością pomimo braku w podanym przykładzie.
Robert Muil

13
x = 'aaa'
L = ['aaa-12', 'bbbaaa', 'cccaa']
res = [y for y in L if x in y]

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

3
Jeśli zamierzasz przyjąć takie podejście, myślę, że bardziej idiomatyczne jest if 'abc' in itemraczej używanie item.find('abc') == -1.
Wyatt Baldwin,


4

Użyj __contains__()metody klasy łańcuchowej Python:

a = ['abc-123', 'def-456', 'ghi-789', 'abc-456']
for i in a:
    if i.__contains__("abc") :
        print(i, " is containing")

3

Jestem nowy w Pythonie. Poniższy kod działał i ułatwiłem zrozumienie:

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)

W Python3.6 daje to błąd: TypeError: oczekiwany ciąg znaków lub obiekt podobny do bajtów
AimForClarity 13.08.18

1
@AimForClarity Tak. re.findall w python3.6 oczekuje ciągu. Alternatywą byłoby przekształcenie listy w ciąg znaków 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
Przepraszamy za złe formatowanie. Z jakiegoś powodu nie mogłem zrobić odpowiednich podziałów linii.
arun_munagala

0

Przeprowadziłem wyszukiwanie, które wymaga wprowadzenia określonej wartości, a następnie wyszuka wartość z listy zawierającej dane wejściowe:

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)

Spróbuj wyszukać „abc”.


0
def find_dog(new_ls):
    splt = new_ls.split()
    if 'dog' in splt:
        print("True")
    else:
        print('False')


find_dog("Is there a dog here?")

0

Potrzebowałem indeksów listy, które odpowiadają dopasowaniu w następujący sposób:

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

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

wynik

[0, 3]

-1

Pytanie: Podaj informacje abc

    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

Z mojej wiedzy stwierdzenie „za” zawsze pochłania czas.

Gdy długość listy rośnie, czas wykonania również rośnie.

Myślę, że wyszukiwanie podłańcucha w łańcuchu za pomocą instrukcji „is” jest nieco szybsze.

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

Ale zgadzam się, że anyoświadczenie jest bardziej czytelne.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.