Check if substring is in a list of strings?

Question:

I have found some answers to this question before, but they seem to be obsolete for the current Python versions (or at least they don’t work for me).

I want to check if a substring is contained in a list of strings. I only need the boolean result.

I found this solution:

word_to_check = 'or'
wordlist = ['yellow','orange','red']

result = any(word_to_check in word for word in worldlist)

From this code I would expect to get a True value. If the word was “der”, then the output should be False.

However, the result is a generator function, and I can’t find a way to get the True value.

Any idea?

Asked By: Álvaro

||

Answers:

You can import any from __builtin__ in case it was replaced by some other any:

>>> from  __builtin__ import any as b_any
>>> lst = ['yellow', 'orange', 'red']
>>> word = "or"
>>> b_any(word in x for x in lst)
True

Note that in Python 3 __builtin__ has been renamed to builtins.

Answered By: Ashwini Chaudhary

You could use next instead:

colors = ['yellow', 'orange', 'red'] 
search = "or"

result = next((True for color in colors if search in color), False)

print(result) # True

To show the string that contains the substring:

colors = ['yellow', 'orange', 'red'] 
search = "or"

result = [color for color in colors if search in color]  

print(result) # Orange
Answered By: stderr

Posted code

The OP’s posted code using any() is correct and should work. The spelling of "worldlist" needs to be fixed though.

Alternate approach with str.join()

That said, there is a simple and fast solution to be had by using the substring search on a single combined string:

>>> wordlist = ['yellow','orange','red']
>>> combined = 't'.join(wordlist)

>>> 'or' in combined
True
>>> 'der' in combined
False

For short wordlists, this is several times faster than the approach using any.

And if the combined string can be precomputed before the search, the in-operator search will always beat the any approach even for large wordlists.

Alternate approach with sets

The O(n) search speed can be reduced to O(1) if a substring set is precomputed in advance and if we don’t mind using more memory.

Precomputed step:

from itertools import combinations

def substrings(word):
    for i, j in combinations(range(len(word) + 1), 2):
        yield word[i : j]

wordlist = ['yellow','orange','red']
word_set = set().union(*map(substrings, wordlist))

Fast O(1) search step:

>>> 'or' in word_set
True
>>> 'der' in word_set
False
Answered By: Raymond Hettinger

Also if someone wants to check if any of the values of a dictionary exists as a substring in a list of strings, can use this:

list_a = [
    'Copy of snap-009ecf9feb43d902b from us-west-2',
    'Copy of snap-0fe999422014504b6 from us-west-2',
    'Copy of snap-0fe999422014cscx504b6 from us-west-2',
    'Copy of snap-0fe999422sdad014504b6 from us-west-2'
]
dict_b = {
    '/dev/xvda': 'snap-0fe999422014504b6',
    '/dev/xvdsdsa': 'snap-sdvcsdvsdvs'
}

for b1 in dict_b.itervalues():
    result = next( ("found" for a1 in a if b1 in a1), "not found")
    print result 

It prints

not found
found
Answered By: Kostas Demiris
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.