antonioplacerda
antonioplacerda

Reputation: 139

List comprehension: retrieve valid strings if not contained in a list of substrings

I need to check if a list of filenames can be copied and I check this against a list of fobidden substrings.

Here is what I have:

exclude = ['ex','xe']
files = ['include', 'exclude']

And this is what I expect:

['include']

I already got it working with a list comprehension, like this:

[a[0] for a in [(f, any([e in f for e in exclude])) for f in files] if not a[1]]

Where I create a tuple (f, any([e in f for e in exclude])) checking if there is any correspondence on the filename to the excluding substrings. I do this for every file in the list of files for f in files and include only those that don't exist on the excluding substrings if not a[1].

Is there a better way to this? A more pythonic one? Because I'm looping through the file list 2 times and I'm guessing there is a way to this in one go!

Thank you!

Upvotes: 1

Views: 882

Answers (2)

Sevy
Sevy

Reputation: 698

This will only loop through the file list one time:

[file for file in files if not any(item in file for item in exclude)]

It does loop through the exclude list once for every item in the file list so if you have a long exclude list the performance might take a hit.

Upvotes: 0

Jean-François Fabre
Jean-François Fabre

Reputation: 140256

I don't really understand your logic. Looks like you're building tuples with boolean values, then filter the False values out.

It seems to me that this also works and is simpler:

exclude = ['ex','xe']
files = ['include', 'exclude']

print([x for x in files if not any(e in x for e in exclude)])

it loops through files, and for each file, checks that no exclude member is included in it.

Note that you don't have to build an actual list in any. Omit the square brackets, let any perform a lazy evaluation, it's faster.

Upvotes: 6

Related Questions