Home > Enterprise >  More pythonic way to filter objects from a list of dicts based on a dict value that must not contain
More pythonic way to filter objects from a list of dicts based on a dict value that must not contain

Time:01-09

As I'm coming from Java, I wonder if there is a more pythonic approach to achieve the following logic:

movies = [{'original_title': 'Star Wars'}, {'original_title': 'Avengers'}, {'original_title': 'After Love'}]
blacklist = ['Star', 'Love']

filtered_movies = []
for movie in movies:
    blacklisted = False
    for item in blacklist:
        if item in movie['original_title']:
            blacklisted = True
            break
    if not blacklisted:
        filtered_movies.append(movie)

return filtered_movies

filtered_movies then only contains the item {'original_title': 'Avengers'}.

CodePudding user response:

You can do this with a list comprehension:

filtered_movies = [movie for movie in movies 
                   if not any(
                      item in movie['original_title']
                      for item in blacklist
                   )]

For example:

>>> movies = [{'original_title': 'Star Wars'}, {'original_title': 'Avengers'}, {'original_title': 'After Love'}]
>>> blacklist = ['Star', 'Love']
>>> filtered_movies = [movie for movie in movies
... if not any(item in movie['original_title'] for item in blacklist)]
>>> filtered_movies
[{'original_title': 'Avengers'}]

This is a pretty canonical way of performing this sort of filtering operation; the builtin any (used here) and all methods are particularly useful for this.

CodePudding user response:

I would have done it like this, but no idea if this is a more pythonic approach.

movies = [
    {'original_title': 'Star Wars'},
    {'original_title': 'Avengers'},
    {'original_title': 'After Love'},
]
blacklist = ['Star', 'Love']

filtered_movies = []
for movie in movies:
    if any(word in movie['original_title'] for word in blacklist):
        continue
    filtered_movies.append(movie)

print(filtered_movies)

CodePudding user response:

Here you go using filter and lambda function and set

>>> list(filter(lambda x: len(set(blacklist) & set(x["original_title"].split())) == 0, movies))
[{'original_title': 'Avengers'}]

if splitting is not allowed then:

>>> list(filter(lambda x: len([1 for y in blacklist if y in x["original_title"]])==0, movies))
[{'original_title': 'Avengers'}]
>>> list(filter(lambda x: not any(1 for y in blacklist if y in x["original_title"]), movies))
[{'original_title': 'Avengers'}]
  • Related