1

Bit of an odd one I've got here...

Basically say I have a list with lists inside of it.

ratings = [
    # ''' 1 star '''
    ["Strangers on a Train", "Anchorman", "Saw", "Suicide Squad"],

    # ''' 2 star '''
    ["Shutter Island", "Shaun of the Dead", "Scream", "Indiana Jones"],

    # ''' 3 star'''
    ["Goodfellas", "Mr Bean", "The Ring", "Dark Knight"],

    # ''' 4 star'''
    ["Scarface", "Hot Fuzz", "Nosferatu", "Die Hard"],

    # ''' 5 star'''
    ["Pulp Fiction", "Airplane", "The Omen", "Deadpool"]
]

Obviously this is a list of movies, and inside the list is 5 lists giving each of the movies a rating out of 5, although this context is quite useless.

def rating():
    if userInfo[7] == "1":
        return range(5)
    elif userInfo[7] == "2":
        return range(2, 5)
    elif userInfo[7] == "3":
        return range(3, 5)
    elif userInfo[7] == "4":
        return range(4, 5)
    else:
        return range(5, 5)

Here is a function where essentially a range is returned depending on what minimum rating of film they would like to see is. So say their minimum rating is 4, they will only see films of rating 4 and 5.

say they have a list of movies

movies = ["Strangers on a Train", "Anchorman", "Shutter Island",
          "Shaun of the Dead", "Goodfellas", "Mr Bean",
          "Scarface", "Hot Fuzz", "Pulp Fiction", "Airplane"]

Now I want to remove all the movies from this list which are not of rating 4 or above.

I tried

new = []
for item in movies:
    if item not in in ratings[rating()]:
        new.append(item)

but this will not work as I cannot use a range to search through multiple lists inside the big list as it needs to be an integer.

I understand this is a huge post for such a small problem but my brain is dying and I have been trying to do this for hours and I want to sleep but need to do this.

Laurent LAPORTE
  • 21,958
  • 6
  • 58
  • 103

1 Answers1

2

First, the ratings data is really not optimal for a performant search. So I would make a dictionary with movie names as keys and ratings as values using a dictionary comprehension:

movie_rating = {name:i+1 for i,mlist in enumerate(ratings) for name in mlist}

(this dictionary can be reused many times)

Then I apply this data to the second list within a list comprehension. Unrated movies get 0 score.

print([x for x in movies if movie_rating.get(x,0) >= 4])

result:

['Scarface', 'Hot Fuzz', 'Pulp Fiction', 'Airplane']

This method may not be the shortest but has the advantage of keeping exact rating information, and not "ratings above n".

You can read about list and dict comprehensions in this other SO Q & A. The question already explains listcomps very well, and the answer explains dictcomps.

Community
  • 1
  • 1
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • You are a GODSEND. This definitely works, but I seriously have no idea what you have done, I can't get my head around comprehensions seemingly, Do you have any resources that are useful in helping understand them? If you don't, don't worry about it and thanks for your time :D – Matthew Pearson Nov 15 '16 at 21:46
  • I have edited my post to link to a great SO Q&A, it's very clear there. you could do with classical "for" loops but listcomps are way more elegant, fast to write and fast to execute. – Jean-François Fabre Nov 15 '16 at 21:53