How to check if a string is a substring of items in a list of strings
Asked Answered
N

17

873

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:
Nate answered 30/1, 2011 at 13:29 Comment(3)
To check the opposite (if one string contains one among multiple strings): https://mcmap.net/q/54816/-how-to-check-if-a-string-contains-an-element-from-a-list-in-pythonSuccuss
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 stringCallipash
See also this answer by Raymond Hettinger (which should rather be an answer to this question).Fredi
A
1365

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]
Aubert answered 30/1, 2011 at 13:32 Comment(19)
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?Aerometer
Another way to get all strings containing substring 'abc': filter(lambda element: 'abc' in element, some_list)Accidental
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)Guppy
@alldayremix How would I return the index number for that search? if myitem in myarray: return index_number or something.Yenta
@p014k: use the index() method: try: return mylist.index(myitem); except ValueError: passAubert
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])Hawsepipe
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? :/Verein
@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.Aubert
In the above code why is ANY needed? I mean I would expect: if "abc" , and not if any "abc"Verein
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])Amarillo
@Amarillo 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.)Aubert
@SvenMarnach Sorry, I was wrong. I got confused since I was using ipython --pylab, where numpy.any is called instead of builtin anyAmarillo
@Amarillo 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.Aubert
Check multiple substrings in URL: any([substring in "example.com/?query1=foo?query2=bar" for substring in some_list])Resh
If you want to compare case insensitive use: matching = [s for s in some_list if "abc".lower() in s.lower()]Chard
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 [].Misconception
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?Ambriz
@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.Aubert
@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.Ambriz
B
238

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']
Bianka answered 3/8, 2014 at 6:0 Comment(3)
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.Sadomasochism
AMAZING - in a similar situation I would use pandas str.contains, but with lists this is perfectFrans
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)]Ayer
H
107

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]
Hat answered 30/1, 2011 at 13:34 Comment(0)
H
103

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. []', ).

Herpetology answered 13/4, 2016 at 8:19 Comment(12)
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 stringGodhood
Yes, this is the intended behaviour... true if any of the items contain 'abc'Herpetology
I don't know why all these other people decide to do those convoluted lambda solutions when they don't need to! Nice job @HerpetologyRadcliffe
Actually the same question almost answers itself... I just added 3 letters to it.Herpetology
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.Herby
['ab', 'c'] has no 'abc' item, but str(['ab', 'c']) will have an 'abc' match.Porringer
@konst54 it will not match... Give it a try on your console so you can see by yourself.Herpetology
@Herpetology I see. Was not obvious for me, thought it would give a string of concatenated elements, not array structure stringified, sorry. Thanks for clarification.Porringer
TypeError: can only concatenate str (not "list") to strPolliwog
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.Polymorphism
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.Herpetology
@RogerS, That's good solution, How can I also print that specific item where 'abc' is found?Dinh
B
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?

Bermudez answered 20/10, 2011 at 13:24 Comment(4)
Wouldn't [el for el in lst if el and (st in el)] make more sense in the given example?Adactylous
@tinix I don't that will handle non-iterable objects gracefully, will it?Bermudez
"given example" my_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456'] no need to over complicate it.Adactylous
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.Bermudez
S
16
x = 'aaa'
L = ['aaa-12', 'bbbaaa', 'cccaa']
res = [y for y in L if x in y]
Socha answered 30/1, 2011 at 13:31 Comment(0)
S
12
for item in my_list:
    if item.find("abc") != -1:
        print item
Stirps answered 30/1, 2011 at 13:38 Comment(1)
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.Zoes
A
10
any('abc' in item for item in mylist)
Accost answered 30/1, 2011 at 13:34 Comment(0)
O
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)
Octavla answered 7/4, 2018 at 7:52 Comment(0)
G
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")
Guelders answered 8/2, 2019 at 16:37 Comment(0)
K
5

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]
Kirby answered 5/1, 2020 at 19:2 Comment(0)
T
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']
Tiddly answered 14/7, 2020 at 2:43 Comment(0)
Q
1
mylist=['abc','def','ghi','abc']

pattern=re.compile(r'abc') 

pattern.findall(mylist)
Quadroon answered 4/7, 2018 at 13:32 Comment(3)
In Python3.6 this gives an error: TypeError: expected string or bytes-like objectHook
@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)Quadroon
Sorry for the poor formatting. Couldnt do proper line breaks for some reason.Quadroon
A
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])
Abercromby answered 18/2, 2021 at 2:38 Comment(0)
A
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)
Arista answered 16/3, 2018 at 9:14 Comment(0)
E
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'.

Ethelred answered 26/1, 2019 at 2:44 Comment(0)
D
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?")
Dettmer answered 18/7, 2019 at 8:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.