Skip to content

S3Q1 · YouTube Video Engagement Analysis

⚡ Quick Reference

Five functions on a list of video dicts (title, views, likes, comments):

def total_engagement(video: dict) -> int:
    return video["likes"] + video["comments"]

def engagement_rate(video: dict) -> float:
    if video["views"] == 0:
        return 0.0
    return round((video["likes"] + video["comments"]) / video["views"] * 100, 2)

def most_engaging_video(videos: list) -> str:
    return max(videos, key=lambda v: engagement_rate(v))["title"]

def videos_with_engagement_rate_above_threshold(videos: list, threshold: float) -> list:
    return [v["title"] for v in videos if engagement_rate(v) > threshold]

def average_engagement_rate(videos: list) -> float:
    active = [v for v in videos if v["views"] > 0]
    return round(sum(engagement_rate(v) for v in active) / len(active), 2)

Key rules: - engagement_rate(likes + comments) / views * 100, rounded to 2 dp - Zero views → return 0.0 (avoid division by zero) - most_engaging_video → ties broken by first in list (max scans left to right) - average_engagement_rate → excludes videos with zero views


Problem Statement

Problem

Implement five functions that analyse a list of YouTube video dictionaries, each with keys "title", "views", "likes", and "comments".

Sample data:

videos = [
    {"title": "Python Tutorial",  "views": 10000, "likes": 800,  "comments": 200},
    {"title": "Web Dev Crash",    "views": 5000,  "likes": 600,  "comments": 100},
    {"title": "Data Science 101", "views": 8000,  "likes": 400,  "comments": 50},
    {"title": "AI for Beginners", "views": 0,     "likes": 0,    "comments": 0},
]

Function 1 -total_engagement

Simply sum likes and comments:

def total_engagement(video: dict) -> int:
    return video["likes"] + video["comments"]
Video Likes Comments Total
Python Tutorial 800 200 1000
Web Dev Crash 600 100 700
Data Science 101 400 50 450

Function 2 -engagement_rate

engagement_rate = (likes + comments) / views * 100
def engagement_rate(video: dict) -> float:
    if video["views"] == 0:
        return 0.0
    return round((video["likes"] + video["comments"]) / video["views"] * 100, 2)
Video Calculation Rate
Python Tutorial 1000 / 10000 * 100 10.0
Web Dev Crash 700 / 5000 * 100 14.0
Data Science 101 450 / 8000 * 100 5.63
AI for Beginners views = 0 0.0

Function 3 -most_engaging_video

Return the title with the highest engagement rate. For ties, return the first one in the list.

def most_engaging_video(videos: list) -> str:
    return max(videos, key=lambda v: engagement_rate(v))["title"]

max(videos, key=...) scans left to right and keeps the first maximum found -so ties are broken by position automatically.

For the sample data: Web Dev Crash has rate 14.0 -highest → "Web Dev Crash".


Function 4 -videos_with_engagement_rate_above_threshold

Return titles of videos with rate strictly greater than the threshold:

def videos_with_engagement_rate_above_threshold(videos: list, threshold: float) -> list:
    return [v["title"] for v in videos if engagement_rate(v) > threshold]

For threshold = 10.0: Web Dev Crash (14.0 > 10.0) qualifies; Python Tutorial (10.0 = 10.0) does not (strict >).


Function 5 -average_engagement_rate

Average engagement rate of videos with non-zero views only:

def average_engagement_rate(videos: list) -> float:
    active = [v for v in videos if v["views"] > 0]
    return round(sum(engagement_rate(v) for v in active) / len(active), 2)

For the sample: exclude "AI for Beginners" (views=0). Average of [10.0, 14.0, 5.63] = 29.63 / 3 = 9.88.


Complete solution approaches

def total_engagement(video: dict) -> int:
    return video["likes"] + video["comments"]

def engagement_rate(video: dict) -> float:
    if video["views"] == 0:
        return 0.0
    return round((video["likes"] + video["comments"]) / video["views"] * 100, 2)

def most_engaging_video(videos: list) -> str:
    return max(videos, key=lambda v: engagement_rate(v))["title"]

def videos_with_engagement_rate_above_threshold(videos: list, threshold: float) -> list:
    return [v["title"] for v in videos if engagement_rate(v) > threshold]

def average_engagement_rate(videos: list) -> float:
    active = [v for v in videos if v["views"] > 0]
    return round(sum(engagement_rate(v) for v in active) / len(active), 2)
def total_engagement(video: dict) -> int:
    return video["likes"] + video["comments"]

def engagement_rate(video: dict) -> float:
    if video["views"] == 0:
        return 0.0
    rate = (video["likes"] + video["comments"]) / video["views"] * 100
    return round(rate, 2)

def most_engaging_video(videos: list) -> str:
    best = videos[0]
    for v in videos[1:]:
        if engagement_rate(v) > engagement_rate(best):
            best = v
    return best["title"]

def videos_with_engagement_rate_above_threshold(videos: list, threshold: float) -> list:
    result = []
    for v in videos:
        if engagement_rate(v) > threshold:
            result.append(v["title"])
    return result

def average_engagement_rate(videos: list) -> float:
    active = [v for v in videos if v["views"] > 0]
    total = sum(engagement_rate(v) for v in active)
    return round(total / len(active), 2)
def total_engagement(video: dict) -> int:
    return video["likes"] + video["comments"]

def engagement_rate(video: dict) -> float:
    if video["views"] == 0:
        return 0.0
    return round((video["likes"] + video["comments"]) / video["views"] * 100, 2)

def most_engaging_video(videos: list) -> str:
    return max(videos, key=lambda v: engagement_rate(v))["title"]

def videos_with_engagement_rate_above_threshold(videos: list, threshold: float) -> list:
    return list(map(
        lambda v: v["title"],
        filter(lambda v: engagement_rate(v) > threshold, videos)
    ))

def average_engagement_rate(videos: list) -> float:
    active = list(filter(lambda v: v["views"] > 0, videos))
    rates = list(map(engagement_rate, active))
    return round(sum(rates) / len(rates), 2)

filter(lambda v: ..., videos) selects qualifying videos. map(lambda v: v["title"], ...) extracts titles. map(engagement_rate, active) computes all rates in one pass.


Key takeaways

01

max(iterable, key=lambda) for "highest by criterion"

max(videos, key=lambda v: engagement_rate(v)) finds the video with the highest rate. Tie-breaking is automatic -max returns the first maximum found scanning left to right.

02

Guard against zero views

Always check if views == 0: return 0.0 before dividing. Even if the problem says views are positive, defensive coding prevents ZeroDivisionError on edge cases.

03

Reuse engagement_rate in every function

Define engagement_rate once and call it in all other functions. Never rewrite the formula -if it changes, you only update one place.