0
\$\begingroup\$

I want to create a program that can print the number of movies that was watched by more than 3 people (data stored in a nested list as below ).

list_movies = [('Spiderman 3', ['John', 'jake','Ronald']),('Gravity',['james','jake','john','gerald']),
               ('Terminator',['Anne','Johnny','Peter','Ronald','Neville'])]



count2 = 0
for (movie,name) in list_movies:
    count = 0
    for (name) in list_movies:
        if name != '':
            count += 1
    if count > 3:
        count2 += 1

print(count)
print(count2)
\$\endgroup\$
  • 4
    \$\begingroup\$ What happens if you use list_movies = [('Gravity',['james','jake','john','gerald']), ('Terminator',['Anne','Johnny','Peter','Ronald','Neville'])]? Can you understand why? \$\endgroup\$ – 301_Moved_Permanently Oct 22 '18 at 7:38
  • \$\begingroup\$ Would you care to explain \$\endgroup\$ – Nisan Abeywickrama Oct 22 '18 at 11:40
  • \$\begingroup\$ Why are you using a tuple over a dict? \$\endgroup\$ – Fendec Oct 22 '18 at 11:44
  • \$\begingroup\$ Well, removing the spiderman movie will print 2 and 0 instead of the (I guess) expected 5 and 2. This means the code is not working as intended. \$\endgroup\$ – 301_Moved_Permanently Oct 22 '18 at 11:47
  • 2
    \$\begingroup\$ @MathiasEttinger To the best of the authors knowledge. I'm not sure if it falls in that category, else I'll make my answer a community answer.... \$\endgroup\$ – Ludisposed Oct 22 '18 at 11:56
2
\$\begingroup\$
  1. Make it a function

    This should really be a function for test ability, reuse ability

    It would need to be a function which accepts 2 parameters (The list we want to query, the amount of people have had to watch it)

    And it will return the amount of times this happened

    • Add doc strings to said function, so after a while when you come back to this code, you still understand what you have written

    For example:

    def list_movies(movie_list, n):
        """
        a method what returns the count of movies watched by more then n people
    
        args:
            movie_list (list): The list of movies in [(movie, [names]), ..]
            n (int): The amount of times the movies has need to be watched
    
        returns:
           The count of movies that has been watched by more then n people
        """
    
  2. Make proper tests

    if you had properly tested this code, @Mathias's comment would probably not be necessary

    There are a few good modules to test functionality doctest or unittests

    Let's use doctest and add some tests to the docstring:

    >>> count_movies_watched([('Spiderman 3', ['John', 'jake','Ronald']),('Gravity',['james','jake','john','gerald'])], 3)
    1
    
    >>> count_movies_watched([('Spiderman 3', ['John', 'jake','Ronald']),('Gravity',['james','jake','john','gerald'])], 4)
    0
    

Without even writing a single line of code, it's already more clear, what this function will do and what a correct answer will be.

Improving Code

  • You can use list comprehension and the built in sum to get a count of movies
  • Use _ for variables you don;t use later on

Netting me:

sum([1 if len(names) > n else 0 for _, names in movie_list])

But this can also be improved, as @Mathias correctly states

  • sum will accept any iterable there is no need for the list comprehension
  • sum can add bools as well so no need for the awkward ternary

Netting me:

sum(len(names) > n for _, names in movie_list)

Putting it all together

import doctest

def count_movies_watched(movie_list, n):
    """
    a method what returns the count of movies watched by more then n people

    args:
        movie_list (list): The list of movies in [(movie, [names]), ..]
        n (int): The amount of times the movies has need to be watched

    returns:
        The count of movies that has been watched by more then n people

    >>> count_movies_watched([('Spiderman 3', ['John', 'jake','Ronald']),('Gravity',['james','jake','john','gerald'])], 3)
    1

    >>> count_movies_watched([('Spiderman 3', ['John', 'jake','Ronald']),('Gravity',['james','jake','john','gerald'])], 4)
    0
    """
    return sum(len(names) > n for _, names in movie_list)

if __name__ == '__main__':
    doctest.testmod()
\$\endgroup\$
  • \$\begingroup\$ It would be great if i get a detailed code. This seems quite complicated as a I'm a beginner. \$\endgroup\$ – Nisan Abeywickrama Oct 31 '18 at 5:20
  • \$\begingroup\$ @NisanAbeywickrama As your questions is off topic, I'm afraid I won't be able to add much more to this answer. What is complicated for you, I might shed some light on it \$\endgroup\$ – Ludisposed Oct 31 '18 at 8:59

Not the answer you're looking for? Browse other questions tagged or ask your own question.