Day 5 of 80

Lists & Collections

Phase 1: Python Foundation

What You'll Build Today

Welcome to Day 5! Today marks a massive shift in your ability to write useful software. Up until now, we have been dealing with single pieces of data: one number, one string of text, or one boolean flag.

But think about the real world. A chat history isn't one string; it's a sequence of twenty messages. A search result isn't one website; it's a collection of ten links. A dataset isn't one number; it's thousands of rows.

Today, we are building a Todo List Manager. While it sounds simple, this is the exact same logic used to manage conversation history in chatbots like ChatGPT.

Here is what you will master today:

* List Creation: How to create a single variable that holds thousands of items.

* Indexing and Slicing: How to pinpoint specific data (like the very first message) or grab a subset (like the last 3 messages for context).

* Methods (.append, .pop): How to dynamically grow and shrink your data as the program runs.

* List Comprehensions: A powerful, professional Python tool to filter and modify lists in a single line of code.

The Problem

Let's imagine you are trying to build a chatbot that remembers what the user said. Based on what you know so far, you might try to create a variable for every single message.

Look at this code. It is painful to write, and even more painful to read.

# The "Painful" Way to store history

msg_1 = "Hi, I am user 1."

msg_2 = "Hello user, how can I help?"

msg_3 = "I need to fix my python code."

msg_4 = "Sure, paste your code here."

msg_5 = "print('hello')"

# Now, imagine trying to search through these messages. # You have to write an if-statement for EVERY variable.

search_term = "python"

if search_term in msg_1:

print("Found in message 1")

elif search_term in msg_2:

print("Found in message 2")

elif search_term in msg_3:

print("Found in message 3")

# ... we have to keep going forever.

Why is this broken?

  • It doesn't scale. What if the conversation goes on for 100 turns? Do you write 100 variables?
  • It isn't dynamic. You cannot write code for msg_100 if you don't know yet if the user will type 100 things.
  • Maintenance is a nightmare. If you want to delete the oldest message to save memory, you have to manually shift every single variable (msg_1 = msg_2, msg_2 = msg_3...).
  • There has to be a container that can grow, shrink, and let us loop through everything at once. That container is a List.

    Let's Build It

    We are going to build a dynamic Todo List Manager. We will start small and add features step-by-step.

    Step 1: Creating a List

    A list in Python is defined by square brackets []. You can put anything inside it—strings, numbers, or even other lists.

    # Creating a list with some initial data
    

    tasks = ["Learn Python", "Build AI App", "Drink Coffee"]

    print(tasks)

    # We can also create an empty list to fill later

    chat_history = []

    print(chat_history)

    Why this matters: You now have a single variable name (tasks) that represents a group of items. You can pass tasks around your program as one unit.

    Step 2: Accessing Data (Indexing)

    Python uses "zero-indexing." This means the first item in the list is at position 0, not 1. This is the most common mistake for beginners.

    tasks = ["Learn Python", "Build AI App", "Drink Coffee"]
    
    

    first_task = tasks[0] # This gets "Learn Python"

    second_task = tasks[1] # This gets "Build AI App"

    print("First thing to do:", first_task)

    # You can also count from the end using negative numbers

    last_task = tasks[-1] # This gets "Drink Coffee"

    print("Last thing to do:", last_task)

    Why this matters: When you build an AI chatbot, you often need to send the "system prompt" (the first instruction) or the "latest user query" (the last item). Indexing lets you grab exactly what you need.

    Step 3: Slicing (The Context Window)

    Sometimes you don't want just one item; you want a section. In AI, this is crucial for "Context Windows." You might only want to send the AI the last 5 messages so it doesn't get confused by old topics.

    We use the syntax [start:end]. Note that it stops before the end number.

    # Imagine a long conversation history
    

    history = [

    "Hi",

    "Hello",

    "Who are you?",

    "I am a bot",

    "Cool",

    "Bye"

    ]

    # Get the first 2 messages (0 up to, but not including, 2)

    intro = history[0:2]

    print("Intro:", intro)

    # Get the last 3 messages # If you leave the end blank, it goes to the very end

    recent_context = history[-3:]

    print("Recent Context:", recent_context)

    Step 4: Adding and Removing Items

    Lists are mutable (changeable). We can add new tasks and complete old ones.

    * .append(item): Adds to the end.

    * .remove(item): Finds the item and removes it.

    * .pop(index): Removes the item at a specific index.

    tasks = ["Learn Python", "Sleep"]
    
    # 1. Add a new task
    

    print("Adding task...")

    tasks.append("Code Project")

    print(tasks)

    # 2. Remove a task by name

    print("Removing Sleep...")

    tasks.remove("Sleep")

    print(tasks)

    # 3. Remove the first task using pop # .pop() also returns the item it deleted, in case you need it

    print("Completing first task...")

    completed_task = tasks.pop(0)

    print(f"You completed: {completed_task}")

    print(f"Remaining tasks: {tasks}")

    Step 5: The "List Comprehension" (Filtering)

    This is a slightly advanced concept, but it is standard practice in Python. A list comprehension allows you to create a new list based on an existing list in one line. It is incredibly useful for filtering data.

    Imagine we want to find all tasks that contain the word "Code".

    all_tasks = ["Code Python", "Wash dishes", "Code Project", "Walk dog"]
    
    # The Syntax: [ item for item in list if condition ]
    

    coding_tasks = [task for task in all_tasks if "Code" in task]

    print("Original:", all_tasks)

    print("Filtered:", coding_tasks)

    Why this matters: In AI, you often need to filter "toxic" words out of a user's input or select only high-quality documents from search results. Comprehensions make this fast and readable.

    Step 6: Putting it together (The Todo App)

    Let's combine loops (from yesterday) with lists to make an interactive tool.

    # Initialize empty list
    

    todo_list = []

    print("--- TODO MANAGER ---")

    print("Commands: add, view, remove, quit")

    while True:

    action = input("\nWhat would you like to do? ").lower()

    if action == "quit":

    print("Goodbye!")

    break

    elif action == "add":

    item = input("Enter task: ")

    todo_list.append(item)

    print(f"Added '{item}' to the list.")

    elif action == "view":

    print("\nYour List:")

    # We use 'enumerate' to get the index numbers automatically

    for index, task in enumerate(todo_list):

    print(f"{index}. {task}")

    elif action == "remove":

    # First show the list so they know the numbers

    print("\nYour List:")

    for index, task in enumerate(todo_list):

    print(f"{index}. {task}")

    try:

    num = int(input("Enter the number to remove: "))

    removed = todo_list.pop(num)

    print(f"Removed '{removed}'")

    except:

    print("Error: Invalid number.")

    else:

    print("I don't understand that command.")

    Now You Try

    You have a working Todo Manager. Now, extend its functionality to practice your new skills.

  • The "Clear All" Feature:
  • Add a command called clear. When the user types this, it should empty the entire list. (Hint: You can use the .clear() method, or simply re-assign the variable to an empty list []).

  • The Priority Insert:
  • Right now, .append() adds to the bottom. Add a command called top that adds a task to the top (index 0) of the list. (Hint: Look up the .insert() method in Python documentation).

  • The Sorter:
  • Add a command called sort. When typed, it should rearrange the tasks alphabetically. (Hint: Lists have a built-in .sort() method).

    Challenge Project: The Toxic Content Filter

    In GenAI development, "Safety Rails" are critical. You cannot pass user input directly to an LLM without checking it first, or the AI might be tricked into saying something offensive.

    Your challenge is to build a content filter.

    Requirements:
  • Create a list called user_messages containing 5-6 strings. Some should be normal, some should contain "banned" words (e.g., "spam", "virus", "attack").
  • Create a list called banned_words containing those specific bad words.
  • Write a script that iterates through user_messages.
  • If a message contains any of the banned words, exclude it.
  • If a message is clean, add it to a new list called clean_messages.
  • Print the final clean_messages list.
  • Example Input:

    Messages: ["Hello friend", "Click this spam link", "How are you?", "Download this virus"]

    Banned: ["spam", "virus"]

    Example Output: ["Hello friend", "How are you?"] Hints:

    * You will need a loop inside a loop. (For every message, check every banned word).

    * Alternatively, you can use a boolean flag like is_clean = True before checking the banned words. If you find a banned word, set is_clean = False. Only append if is_clean is still True after checking.

    What You Learned

    Today you moved from managing single variables to managing collections of data.

    * Lists []: The primary way to store sequences of data.

    * Indexing [0]: How to retrieve specific items.

    * Slicing [0:5]: How to grab context windows.

    * Methods: .append(), .pop(), and .remove() give your program life and movement.

    * Filtering: Using logic to separate good data from bad data.

    Why This Matters for AI:

    Large Language Models (LLMs) are "stateless"—they don't remember you. When you chat with an AI, your code must send the entire list of previous messages (the history) along with your new question every single time. If you can't manage lists, you can't build a chatbot that remembers its own name.

    Tomorrow:

    We have lists to store sequences, but what if we need to store structured data, like a user profile with a name, email, and ID? Lists are bad at that. Tomorrow, we learn Dictionaries—the key to organizing complex data.