Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sapphire-Selene C. #52

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open

Sapphire-Selene C. #52

wants to merge 28 commits into from

Conversation

secasti
Copy link

@secasti secasti commented Mar 31, 2023

No description provided.

Copy link

@tildeee tildeee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Tagging @charliemushishi to ensure visibility)

Great work on this project, y'all! Your project code gets a "green" in my book.

Overall, your solutions are logical and well thought out. Your approach to each function tells me that you two were always thinking in the right direction.

Most of my feedback really dives into the details of each line. There are many comments about variable names and getting rid of extra lines of code. These pieces of feedback are to help you think more about "what's being used," "what do I need," etc., and to give you more permission to delete code or rename or refactor things. I hope my comments deepen your understanding and help inspire future projects. I hope that some of my suggestions help you think, "Oh! That's a cool refactoring suggestion," and I hope they prompt any questions that you can Slack DM me.

In addition, I'd like to comment that y'alls git hygiene is great, keep it up. My personal preference is to not include "wave 5 passed" etc in the commit messages, and to keep focusing on "what changes does this commit contain." Also, y'alls team reflections are great, too.

Overall, you two did a great job!

Comment on lines +4 to +16
if title is None or genre is None or rating is None:
return None

new_movie = {"title": title, "genre": genre, "rating": rating}

if isinstance(title, str) or isinstance(genre, str) or isinstance(rating, int):
return {
"title": title,
"genre": genre,
"rating": rating
}
else:
return None
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like there are two competing solutions in this function: new_movie is a variable that's never used, and you're validating the parameters twice. Consider this code, which passes the tests:

    if title is None or genre is None or rating is None:
        return None
    return {
            "title": title,
            "genre": genre,
            "rating": rating
    }

There are a lot of ways to write the same thing, so feel free to consider other options, but it would be good to watch for unused variables.

# 2nd function in Wave 1
def add_to_watched(user_data, movie):

(user_data["watched"]).append(movie)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] Maybe y'all added the () around user_data["watched"] to help readability, but in the end, it feels like it doesn't conform with more general Python code style. I'd recommend getting rid of it:

    user_data["watched"].append(movie)

watchlist = user_data.get("watchlist", [])

watchlist.append(movie)
user_data["watchlist"] = watchlist
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this line, you all re-assign the value of user_data["watchlist"] to watchlist. However, the original value of watchlist is a reference to user_data.get("watchlist", []). Therefore, consider the following code:

def add_to_watchlist(user_data, movie):
    user_data.get("watchlist", []).append(movie)    
    return user_data

This code passes the tests! Again, when we .append() to a reference to a list (watchlist aka user_data.get("watchlist", [])), it will affect it everywhere, so we don't need to re-assign user_data["watchlist"] back to watchlist (aka we don't need user_data["watchlist"] = watchlist)

Let me know if you have questions!

def watch_movie(user_data, title):

move_movie = False
index = 0
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this function, index is only being used within the for loop below. In this situation, we don't need to set index = 0 before the for loop-- for loops will make an index and use that! We can delete this line and the tests still pass.

movie = user_data["watchlist"][index]
print(user_data["watchlist"][index])
if move_movie:
(user_data["watched"]).append(movie)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] I'd encourage y'all to style this as user_data["watched"].append(movie)

for friend in user_data["friends"]:
for movie in friend["watched"]:
friends_watched_list.append(movie["title"])
friends_watched_set = set(friends_watched_list)
Copy link

@tildeee tildeee Apr 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When this line is inside of the for loop, it runs every time. However, we only need this to run once-- after we've populated friends_watched_list fully. We can move this line after the nested for loops, and the tests still pass :)

    for friend in user_data["friends"]:
        for movie in friend["watched"]:
            friends_watched_list.append(movie["title"])

    friends_watched_set = set(friends_watched_list)

Comment on lines +107 to +110
if movie["title"] not in friends_watched_set and movie not in friends_list:
friends_list.append(movie)

return friends_list
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my eyes, friends_list isn't the most accurate name for this variable. I might propose unique_movies_list? Consider how this reads:

def get_unique_watched(user_data):

    friends_watched_list = []
    friends_watched_set = None
    unique_movies_list = []

    # other stuff...

    for movie in user_data["watched"]:
        if movie["title"] not in friends_watched_set:
            if movie not in unique_movies_list:
                unique_movies_list.append(movie)

    return unique_movies_list

# 2nd function in Wave 3
def get_friends_unique_watched(user_data):

user_watched = set([movie["title"] for movie in user_data["watched"]])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love this line! It's very dense and compact.

Comment on lines +146 to +155
genre_count = {}
for movie in user_data["watched"]:
genre = movie["genre"]
genre_count[genre] = genre_count.get(genre, 0) + 1
best_genre = None
best_genre_count = 0
for genre, count in genre_count.items():
if count > best_genre_count:
best_genre = genre
best_genre_count = count
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a re-implementation of a function you've alreaady made! :O :P :D Consider this code, where you invoke the other function and get to delete ten lines! And the tests still pass :)

def get_new_rec_by_genre(user_data):

    user_watched = set([movie["title"] for movie in user_data["watched"]])
    friends_unique_watched = get_friends_unique_watched(user_data)

    best_genre = get_most_watched_genre(user_data)

    recommended_movies = []
    # ...

Comment on lines +171 to +178
if user_data["friends"] == []:
return user_favorites
else:
unseen_by_friends = get_unique_watched(user_data)
for movie in unseen_by_friends:
if movie in user_favorites:
recommended_movies.append(movie)
return recommended_movies
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, your code checks if user_data has friends. If the user has friends, then it iterates through the unseen_by_friends list. If the user doesn't have friends, then the function should return an empty list, as there are no recommendations.

However, when we iterate with a for loop over an empty list, the code shouldn't break. There's a way to get rid of this if/else, but it would require fixing a small bug in get_unique_watched. Consider the following:

Imagine that get_unique_watched returned an empty list. If unseen_by_friends is an empty list, then when we do for movie in unseen_by_friends, it will skip over this loop, and recommended_movies will be an empty list. Therefore, with the fix in get_unique_watched, this function could look like this:

def get_rec_from_favorites(user_data):
    
    user_favorites = user_data["favorites"]
    recommended_movies = []

    unseen_by_friends = get_unique_watched(user_data)
    for movie in unseen_by_friends:
        if movie in user_favorites:
            recommended_movies.append(movie)
    return recommended_movies

I got this version of the code to work if, inside get_unique_watched, I moved the line friends_watched_set = set(friends_watched_list). Refer to that comment for details!

The reason why I like this refactoring is because we get to reduce the amount of validation, and we don't need to repeat it over several functions. Let me know what questions come up!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants