846

How do I search for items that contain the string 'abc' in the following list?

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

The following checks if 'abc' is in the list, but does not detect 'abc-123' and 'abc-456':

if 'abc' in xs:
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
SandyBr
  • 11,459
  • 10
  • 29
  • 27
  • 28
    To check the opposite (if one string contains one among multiple strings): http://stackoverflow.com/a/6531704/2436175 – Antonio Nov 18 '14 at 10:48
  • If the left parts of entries are unique, consider constructing a dict from the list: [Find an entry in a list based on a partial string](https://stackoverflow.com/questions/37042291/find-an-entry-in-a-list-based-on-a-partial-string) – Georgy Feb 06 '19 at 10:19
  • See also [this answer](https://stackoverflow.com/a/16381580) by Raymond Hettinger (which should rather be an answer to this question). – mkrieger1 Aug 11 '21 at 09:38

18 Answers18

1337

To check for the presence of 'abc' in any string in the list:

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

if any("abc" in s for s in xs):
    ...

To get all the items containing 'abc':

matching = [s for s in xs if "abc" in s]
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • I have to check if one item is in an array of 6 elements. Is it quicker to do 6 "if" or is it the same? – Olivier Pons Mar 10 '13 at 00:11
  • 8
    Another way to get all strings containing substring 'abc': `filter(lambda element: 'abc' in element, some_list)` – floer32 May 31 '13 at 20:10
  • But from readability perspective, I would rather put `any("abc" in s for s in some_list)` in another function and say `contains("abc",list)` – Tarik Nov 06 '13 at 00:25
  • @alldayremix How would I return the index number for that search? `if myitem in myarray: return index_number` or something. – bmikolaj Oct 15 '14 at 13:11
  • 3
    @p014k: use the `index()` method: `try: return mylist.index(myitem); except ValueError: pass` – Sven Marnach Oct 16 '14 at 12:02
  • If by any chance `mylist` has a `None` inside it will throw an exception. To fix this: `any(["abc" in s for s in some_list if s])` – Hassek Nov 06 '14 at 16:34
  • I am solving an excersice in which I search for a string in a list. Before lookin the above solution, I used: for string in list: if "blabla" in string -> do something! Which did not work... Then I saw this and tried: if "blabla" is string for string in list: and it it did not work... I HAD to use both the parenthesis and the ANY.. Why? :/ – midkin Feb 15 '15 at 17:13
  • 2
    @midkin: I neither understand what exactly you were trying to do, nor how it went wrong. You'll probably have more luck by asking a new question (with the "Ask Question" button), copying your exact code, what you would have expected the code to do, and what it actually did. "Did not work" is completely meaningless unless you define what "works" means in this context, but even then it's better to explain what actually happened instead of saying what didn't. – Sven Marnach Feb 16 '15 at 13:11
  • In the above code why is ANY needed? I mean I would expect: if "abc" , and not if any "abc" – midkin Feb 16 '15 at 13:14
  • A warning: in Python 3, you will need to put brackets around the contents of the generator, otherwise any will return a generator object, which is always True as a condition. I.e. use `any(['abc' in s for s in some_list])` – YuppieNetworking Dec 17 '15 at 08:53
  • @YuppieNetworking No, you shouldn't add the square brackets, even in Python 3. The built-in function `any()` always returns a Boolean value in any Python version that supports it. (Not sure what gave you the idea you need the square brackets.) – Sven Marnach Jan 11 '16 at 15:58
  • @SvenMarnach Sorry, I was wrong. I got confused since I was using ipython --pylab, where numpy.any is called instead of builtin any – YuppieNetworking Jan 11 '16 at 19:06
  • @YuppieNetworking Ah, that explains it. Using `from numpy import *` or `--pylab` causes quite a bit confusion due to shadowed built-ins, which is why I tend to avoid it. – Sven Marnach Jan 13 '16 at 13:42
  • Check multiple substrings in URL: any([substring in "http://www.example.com/?query1=foo?query2=bar" for substring in some_list]) – mellow-yellow Feb 13 '16 at 17:21
  • If you want to compare case insensitive use: `matching = [s for s in some_list if "abc".lower() in s.lower()]` – Gürol Canbek Apr 17 '16 at 12:35
  • Just thought I'd add my two cents. This would have to be modified on a list of lists. Ex: sooners = [(('GO', 'OKLAHOMA'), 'GO TO OKLAHOMA')]; row1 = [row[1] for row in test]; matching = [s for s in row1 if 'OKLAHOMA' in s]; print(matching); output: ['GO TO OKLAHOMA']... if you don't define a row, you will get empty brackets []. – spacedustpi Aug 30 '18 at 16:38
  • This appears to also match any the characters are otherwise separately present. i.e. a match will be found if some_list has an ["cba-4123"]. Is a small modification possible to make it only match in the correct order? – Larry Cai Sep 12 '21 at 12:08
  • 1
    @LarryCai The check `"abc" in some_string` will check for presence of `"abc"` as an exact, contiguous substring of `some_string`, so both `"abc" in "cba-4123"` and `"abc" in "a-b-c"` will return `False`. No modification of the code required. – Sven Marnach Sep 13 '21 at 09:12
  • @SvenMarnach Thanks for confirming, it would appear my code/objects are creating this unintended result due to other reasons then. Will do some further troubleshooting. – Larry Cai Sep 13 '21 at 12:14
233

Just throwing this out there: if you happen to need to match against more than one string, for example abc and def, you can combine two comprehensions as follows:

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

Output:

['abc-123', 'def-456', 'abc-456']
fantabolous
  • 21,470
  • 7
  • 54
  • 51
  • 27
    This was exactly what I was googling for.. Thanks! – N8TRO Jul 06 '16 at 21:13
  • 4
    You could also use `{s for s in my_list for xs in matchers if xs in s}` (note the curly brackets to create a unique set). Might be easier to read, but could be slower if most `s` values will have a match, since your `any` will efficiently stop at the first match. – Matthias Fripp Jan 09 '18 at 18:47
  • 2
    AMAZING - in a similar situation I would use pandas str.contains, but with lists this is perfect – data_runner Apr 20 '22 at 06:50
  • 1
    Great, solution. In my case I needed to check if my string (s) had ALL the substrings (xs) from a list (in this case `matchers`). I just changed `any` for `all` and it did the trick: `matching = [s for s in my_list if all(xs in s for xs in matchers)]` – Dan Jan 16 '23 at 22:07
103

Use filter to get all the elements that have 'abc':

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

One can also use a list comprehension:

>>> [x for x in xs if 'abc' in x]
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
MAK
  • 26,140
  • 11
  • 55
  • 86
97

If you just need to know if 'abc' is in one of the items, this is the shortest way:

if 'abc' in str(my_list):

Note: this assumes 'abc' is an alphanumeric text. Do not use it if 'abc' could be just a special character (i.e. []', ).

RogerS
  • 1,322
  • 9
  • 11
  • 2
    This would fail if you had a list of ["abc1", "1abc2"] as it would find a match because the string 'abc' would be in the newly created string – cgseller Jan 26 '17 at 13:20
  • 3
    Yes, this is the intended behaviour... true if any of the items contain 'abc' – RogerS Jan 29 '17 at 19:39
  • 11
    I don't know why all these other people decide to do those convoluted lambda solutions when they don't need to! Nice job @RogerS – ntk4 Sep 14 '17 at 05:30
  • 1
    Actually the same question almost answers itself... I just added 3 letters to it. – RogerS Sep 15 '17 at 13:32
  • 1
    It's a nice solution, but if you want to find _the items_ which contain the given string, you will not succeed. Here you find out if _any_ of the items contains the string. – cslotty May 09 '19 at 09:03
  • ['ab', 'c'] has no 'abc' item, but str(['ab', 'c']) will have an 'abc' match. – Konst54 Jul 03 '20 at 10:25
  • 1
    @konst54 it will not match... Give it a try on your console so you can see by yourself. – RogerS Jul 04 '20 at 11:17
  • @RogerS I see. Was not obvious for me, thought it would give a string of concatenated elements, not array structure stringified, sorry. Thanks for clarification. – Konst54 Jul 04 '20 at 11:22
  • TypeError: can only concatenate str (not "list") to str – Rodrigo Vieira Dec 14 '20 at 17:30
  • 1
    This answer is a little off the mark. Converting the list to a str will result in a string with "[", "]", "'", ",", and " " characters. This could be a problem depending on what you are searching for. Remove the str conversion to search for exact matches in the list. – Samuel Dec 29 '20 at 18:14
  • Samuel if you remove the 'str' conversion you will only get exact matches... The question asked to find 'abc' in particular, which this solution provides. It generalizes well to any normal text. It will not work if your text is only one of special characters that str adds (i.e. '[], ) but this was not the question asked. – RogerS Dec 30 '20 at 01:18
  • @RogerS, That's good solution, How can I also print that specific item where 'abc' is found? – Ramzan Mahmood Aug 10 '22 at 09:01
19

This is quite an old question, but I offer this answer because the previous answers do not cope with items in the list that are not strings (or some kind of iterable object). Such items would cause the entire list comprehension to fail with an exception.

To gracefully deal with such items in the list by skipping the non-iterable items, use the following:

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

then, with such a list:

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

you will still get the matching items (['abc-123', 'abc-456'])

The test for iterable may not be the best. Got it from here: In Python, how do I determine if an object is iterable?

Community
  • 1
  • 1
Robert Muil
  • 2,948
  • 1
  • 24
  • 30
  • Wouldn't `[el for el in lst if el and (st in el)]` make more sense in the given example? – Gordo Oct 01 '16 at 06:20
  • @tinix I don't that will handle non-iterable objects gracefully, will it? – Robert Muil Oct 17 '16 at 08:31
  • "given example" `my_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456']` no need to over complicate it. – Gordo Oct 17 '16 at 20:15
  • 1
    Yes absolutely - the accepted answer is perfectly suitable and my suggestion is more complicated, so feel free to ignore it - I just offered in case someone had the same problem as I had: non-iterable items in such lists are a real-world possibility despite not existing in the given example. – Robert Muil Oct 18 '16 at 18:28
16
x = 'aaa'
L = ['aaa-12', 'bbbaaa', 'cccaa']
res = [y for y in L if x in y]
jamylak
  • 128,818
  • 30
  • 231
  • 230
Mariy
  • 5,746
  • 4
  • 40
  • 57
12
for item in my_list:
    if item.find("abc") != -1:
        print item
jamylak
  • 128,818
  • 30
  • 231
  • 230
Rubycon
  • 18,156
  • 10
  • 49
  • 70
  • 3
    If you're going to take this approach, I think it's more idiomatic to do `if 'abc' in item` rather using `item.find('abc') == -1`. – Wyatt Baldwin Mar 10 '16 at 22:22
10
any('abc' in item for item in mylist)
Imran
  • 87,203
  • 23
  • 98
  • 131
10

I am new to Python. I got the code below working and made it easy to understand:

my_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456']
for item in my_list:
    if 'abc' in item:
       print(item)
Amol Manthalkar
  • 1,890
  • 2
  • 16
  • 16
6

Use the __contains__() method of Pythons string class.:

a = ['abc-123', 'def-456', 'ghi-789', 'abc-456']
for i in a:
    if i.__contains__("abc") :
        print(i, " is containing")
kalehmann
  • 4,821
  • 6
  • 26
  • 36
Harsh Lodhi
  • 159
  • 4
  • 11
3

I needed the list indices that correspond to a match as follows:

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

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

output

[0, 3]
Grant Shannon
  • 4,709
  • 1
  • 46
  • 36
3

If you want to get list of data for multiple substrings

you can change it this way

some_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456']
# select element where "abc" or "ghi" is included
find_1 = "abc"
find_2 = "ghi"
result = [element for element in some_list if find_1 in element or find_2 in element] 
# Output ['abc-123', 'ghi-789', 'abc-456']
Lakhani Aliraza
  • 435
  • 6
  • 8
1
mylist=['abc','def','ghi','abc']

pattern=re.compile(r'abc') 

pattern.findall(mylist)
Bugs
  • 4,491
  • 9
  • 32
  • 41
  • In Python3.6 this gives an error: TypeError: expected string or bytes-like object – AimForClarity Aug 13 '18 at 21:41
  • 2
    @AimForClarity Yes. re.findall in python3.6 expects a string. An alternative would be by converting the list into a string `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 Aug 14 '18 at 12:32
  • 1
    Sorry for the poor formatting. Couldnt do proper line breaks for some reason. – arun_munagala Aug 14 '18 at 12:36
1

Adding nan to list, and the below works for me:

some_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456',np.nan]
any([i for i in [x for x in some_list if str(x) != 'nan'] if "abc" in i])
Sam S.
  • 627
  • 1
  • 7
  • 23
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)
Chandragupta Borkotoky
  • 1,596
  • 1
  • 11
  • 16
0

I did a search, which requires you to input a certain value, then it will look for a value from the list which contains your input:

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)

Try searching for 'abc'.

Pika Supports Ukraine
  • 3,612
  • 10
  • 26
  • 42
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?")
4b0
  • 21,981
  • 30
  • 95
  • 142
-2

Question : Give the informations of 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']
cottontail
  • 10,268
  • 18
  • 50
  • 51
Soudipta Dutta
  • 1,353
  • 1
  • 12
  • 7