Skip to main content

Day 14 - Operating over tables & lists

Skills: None

Pre-reading: 5.1.6

FIXME

Lambda Functions and Combining Lists and Tables

Focus: Introduce anonymous functions (lambda) and show how to combine list and table operations to solve analysis problems with new examples.

1. Introduction & Warm-Up (10 minutes)

  • Recap:
    • Brief review of list operations and the idea of transforming data.
  • Do Now:
    • “Given a list of email addresses, how would you extract the username (the part before the '@')? Write down your thoughts.”
  • Discussion:
    • Share a couple of ideas without full code yet.

2. Lambda: Anonymous Functions (15 minutes)

  • Motivating Example – Extracting Usernames:
    • We want to convert a list of emails to a list of usernames.
  • New Example List:
    emails = [list: "alice@cafe.com", "bob@domain.org", "charlie@cafe.com"]
  • Using a Named Helper Function (Review):
    fun extract-username(email :: String) -> String:
    string-split(email, "@").get(0)
    end

    usernames = L.map(extract-username, emails)
  • Introducing Lambda:
    • Replace the helper with an anonymous function:
      usernames = L.map(lam(email): string-split(email, "@").get(0) end, emails)
  • Interactive Exercise:
    • Ask: “What would be the output of the lambda version? Write it down.”
    • Discuss and verify.
  • Discussion:
    • Benefits of using lambda for simple, one‑off functions.

3. Combining Lists and Tables (20 minutes)

  • Scenario: A local bookstore tracks sales in a table. You want to compute statistics based on the genres of books sold.
  • Example Table:
    book-sales =
    table: title, genre, copies-sold, price
    row: "Mystery at Midnight", "Mystery", 20, 12.99
    row: "Space Adventures", "Sci-Fi", 15, 15.50
    row: "The Last Detective", "Mystery", 25, 11.50
    row: "Future World", "Sci-Fi", 10, 18.00
    row: "Romance in Paris", "Romance", 30, 9.99
    end
  • Task 1: Extract a List of Copies Sold for a Specific Genre
    • Plan:
      1. Filter the table for rows where genre is, say, "Mystery".
      2. Extract the "copies-sold" column.
    • Implementation:
      fun is-mystery(r :: Row) -> Boolean:
      r["genre"] == "Mystery"
      end

      mystery-sales = filter-with(book-sales, is-mystery)
      copies = mystery-sales.get-column("copies-sold")
      avg-mystery = S.mean(copies)
    • Interactive Do Now:
      • “How many mystery books were sold on average?” (Students compute avg-mystery.)
  • Task 2: Combining List Functions with Tables – Analyzing Email Domains
    • Suppose the bookstore has a customer table:
      customers =
      table: name, email
      row: "Alice", "alice@reader.com"
      row: "Bob", "bob@novel.org"
      row: "Charlie", "charlie@reader.com"
      row: "Dana", "dana@books.net"
      end
    • Plan:
      1. Extract the email column.
      2. Use L.map and string-split to get domain names (the part after '@').
      3. Find the distinct domains.
    • Implementation:
      import lists as L
      email-list = customers.get-column("email")
      domains = L.map(lam(email): string-split(email, "@").get(1) end, email-list)
      unique-domains = L.distinct(domains)
    • Interactive Discussion:
      • “Which domain appears most frequently? How might you count the frequency?”
      • Suggest using L.filter or comparing lengths.
  • Do Now (Group Activity):
    • TODO: PROVIDE A BIGGER TABLE FOR THESE
    • Propose multiple task plans for the question: “How many customers with a '.com' email bought more than 10 copies of a book?”
    • Groups discuss different approaches (filtering the table first versus extracting and then filtering a list) and share their plans.

4. Wrap-Up & Reflection (5 minutes)

  • Recap Key Points:
    • Lambda (anonymous functions) let you succinctly express functions, which can be useful when using functions like L.map, etc.
    • Combining list and table operations enables flexible data analysis.