{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "b8220567",
   "metadata": {},
   "source": [
    "# Creating Lists\n",
    "\n",
    "There are several ways to create a new list:\n",
    "\n",
    "- **Square brackets `[]`**: Enclose elements in square brackets (a subscription expression) to create a list literal\n",
    "- **`list()` constructor**: Convert any iterable (strings, ranges, tuples, etc.) into a list\n",
    "- **List comprehension**: Create lists using a concise expression-based syntax\n",
    "- **`split()` method**: Convert a string into a list of words or parts\n",
    "- **Nested lists**: Create lists containing other lists as elements"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d8ef2c4f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "from pathlib import Path\n",
    "\n",
    "# Find project root by looking for _config.yml\n",
    "current = Path.cwd()\n",
    "for parent in [current, *current.parents]:\n",
    "    if (parent / '_config.yml').exists():\n",
    "        project_root = parent\n",
    "        break\n",
    "else:\n",
    "    project_root = Path.cwd().parent.parent\n",
    "\n",
    "# Add project root to path\n",
    "sys.path.insert(0, str(project_root))\n",
    "\n",
    "# Import shared teaching helpers and cell magics\n",
    "from shared import thinkpython, diagram, jupyturtle, structshape\n",
    "from shared.download import download\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc285bfe-a6fa-4653-9aa5-e85d12bc2675",
   "metadata": {},
   "source": [
    "## Basic List Creation\n",
    "\n",
    "The most common way to create a list is by enclosing comma-separated values in square brackets `[]`.\n",
    "\n",
    "**Syntax:**\n",
    "```python\n",
    "list_name = [element1, element2, element3, ...]\n",
    "```\n",
    "\n",
    "The elements can be of any type, and you can mix different types in the same list."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "a16a119b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['apple', 'banana', 'cherry']\n",
      "[1, 2, 3, 4, 5]\n",
      "[]\n"
     ]
    }
   ],
   "source": [
    "### Using square brackets - sequences of items\n",
    "\n",
    "numbers = [1, 2, 3, 4, 5]               ### a list of integers\n",
    "fruits = ['apple', 'banana', 'cherry']  ### a list of strings\n",
    "empty = []                              ### an empty list\n",
    "\n",
    "print(fruits)\n",
    "print(numbers)\n",
    "print(empty)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "45d8be4c",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### EXERCISE: Create Different Types of Lists\n",
    "# Create the following lists:\n",
    "# 1. A list called 'colors' with three color names\n",
    "# 2. An empty list called 'empty_list'\n",
    "# 3. A list called 'mixed' with a string, an integer, and a float\n",
    "### Your code starts here:\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "a77888de",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Colors: ['red', 'blue', 'green']\n",
      "Empty list: []\n",
      "Mixed list: ['hello', 42, 3.14]\n"
     ]
    }
   ],
   "source": [
    "# Solution\n",
    "colors = ['red', 'blue', 'green']\n",
    "empty_list = []\n",
    "mixed = ['hello', 42, 3.14]\n",
    "\n",
    "print(f\"Colors: {colors}\")\n",
    "print(f\"Empty list: {empty_list}\")\n",
    "print(f\"Mixed list: {mixed}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3de936b6",
   "metadata": {},
   "source": [
    "## `list()` Constructor\n",
    "\n",
    "The `list()` constructor converts any **iterable** (strings, ranges, tuples, etc.) into a list. This is useful when you need to convert data from one sequence type to another."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "1e6127e9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['s', 'p', 'a', 'm']\n",
      "[0, 1, 2, 3, 4]\n",
      "[1, 2, 3]\n"
     ]
    }
   ],
   "source": [
    "chars = list('spam')            ### a list of characters\n",
    "nums = list(range(5))           ### a list of numbers from 0 to 4\n",
    "tuple_data = (1, 2, 3)\n",
    "list_data = list(tuple_data)    ### a list created from a tuple\n",
    "\n",
    "print(chars)\n",
    "print(nums)\n",
    "print(list_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "486e5ec1",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### EXERCISE: Convert Using list() Constructor\n",
    "# 1. Convert the string \"Python\" into a list of characters\n",
    "# 2. Create a list of numbers from 10 to 14 using range() and list()\n",
    "### Your code starts here:\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "1277e0e2",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Characters: ['P', 'y', 't', 'h', 'o', 'n']\n",
      "Numbers: [10, 11, 12, 13, 14]\n"
     ]
    }
   ],
   "source": [
    "# Solution\n",
    "chars = list('Python')\n",
    "numbers = list(range(10, 15))\n",
    "\n",
    "print(f\"Characters: {chars}\")\n",
    "print(f\"Numbers: {numbers}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "338430b9-2b95-4568-af95-5a91c809dbcf",
   "metadata": {},
   "source": [
    "## List Comprehension\n",
    "\n",
    "**List comprehension** provides a concise way to create lists based on existing sequences or ranges. It's a powerful and Pythonic approach that often replaces traditional loops. They're a more Pythonic alternative to using `for` loops to build lists.\n",
    "\n",
    "**Basic Syntax:**\n",
    "```python\n",
    "[expression for item in iterable]\n",
    "```\n",
    "\n",
    "**With Condition:**\n",
    "```python\n",
    "[expression for item in iterable if condition]\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "7afb9f75",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Traditional: [0, 1, 4, 9, 16]\n",
      "Comprehension: [0, 1, 4, 9, 16]\n",
      "Even squares: [0, 4, 16, 36, 64]\n"
     ]
    }
   ],
   "source": [
    "# Traditional way\n",
    "squares = []\n",
    "for x in range(5):\n",
    "    squares.append(x**2)\n",
    "print(\"Traditional:\", squares)\n",
    "\n",
    "# List comprehension way\n",
    "squares = [x**2 for x in range(5)]\n",
    "print(\"Comprehension:\", squares)\n",
    "\n",
    "# With condition\n",
    "even_squares = [x**2 for x in range(10) if x % 2 == 0]\n",
    "print(\"Even squares:\", even_squares)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "61bb0fab",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Word lengths: [5, 5, 6, 11]\n",
      "Long words: ['PYTHON', 'PROGRAMMING']\n",
      "Flattened: [1, 2, 3, 4, 5, 6, 7, 8, 9]\n"
     ]
    }
   ],
   "source": [
    "# More complex list comprehensions\n",
    "words = ['hello', 'world', 'python', 'programming']\n",
    "\n",
    "# Get lengths of words\n",
    "lengths = [len(word) for word in words]\n",
    "print(\"Word lengths:\", lengths)\n",
    "\n",
    "# Get uppercase words longer than 5 characters\n",
    "long_words = [word.upper() for word in words if len(word) > 5]\n",
    "print(\"Long words:\", long_words)\n",
    "\n",
    "# Nested comprehension - flatten a 2D list\n",
    "matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n",
    "flattened = [item for row in matrix for item in row]\n",
    "print(\"Flattened:\", flattened)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "2f7ff33f",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### EXERCISE: convert string to uppercase using list comprehension\n",
    "### Hint: use str.upper() method\n",
    "### Your code starts here:\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "6ad04003",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['HELLO', 'WORLD', 'PYTHON']\n"
     ]
    }
   ],
   "source": [
    "# Convert strings to uppercase\n",
    "words = ['hello', 'world', 'python']\n",
    "uppercase_words = [word.upper() for word in words]\n",
    "print(uppercase_words)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "0065d342",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### EXERCISE: Filter list using list comprehension: \n",
    "### Create a new list with only words longer than 5 characters \n",
    "### Hint: use len() function\n",
    "### Your code starts here:\n",
    "words = ['apple', 'banana', 'cherry', 'date', 'elderberry']\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "aa856dfe",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['banana', 'cherry', 'elderberry']\n"
     ]
    }
   ],
   "source": [
    "words = ['apple', 'banana', 'cherry', 'date', 'elderberry']\n",
    "long_words = [word for word in words if len(word) > 5]\n",
    "print(long_words)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "1bc50eec",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### EXERCISE: List Comprehension Practice\n",
    "# 1. Create a list of cubes (x^3) for numbers 1 through 5\n",
    "# 2. Create a list of only odd numbers from 1 to 20\n",
    "### Your code starts here:\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "153a5ae9",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Cubes: [1, 8, 27, 64, 125]\n",
      "Odd numbers: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]\n"
     ]
    }
   ],
   "source": [
    "# Solution\n",
    "cubes = [x**3 for x in range(1, 6)]\n",
    "odds = [x for x in range(1, 21) if x % 2 != 0]\n",
    "\n",
    "print(f\"Cubes: {cubes}\")\n",
    "print(f\"Odd numbers: {odds}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "37703787",
   "metadata": {},
   "source": [
    "## Lists and Strings\n",
    "\n",
    "This section explores common patterns for working with strings and lists, focusing on converting between them and manipulating them together.\n",
    "\n",
    "A string is a sequence of characters and a list is a sequence of values, but a list of characters is not the same as a string. To convert a string to a list of individual characters, use the `list()` function (covered earlier). To break a string into words or parts, use the `split()` method shown below."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dbcd3e40",
   "metadata": {},
   "source": [
    "### `split()` Method\n",
    "\n",
    "The `split()` method breaks a string into a list of words or parts based on a delimiter. By default, it splits on whitespace."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "98faa717",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['hello', 'world', 'python']\n",
      "['apple', 'banana', 'cherry']\n"
     ]
    }
   ],
   "source": [
    "# Split by whitespace (default)\n",
    "words = 'hello world python'.split()\n",
    "print(words)\n",
    "\n",
    "# Split by custom delimiter\n",
    "data = 'apple,banana,cherry'.split(',')\n",
    "print(data)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aaa7963c",
   "metadata": {},
   "source": [
    "You can also use an optional **delimiter** argument to specify which characters to use as word boundaries:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "d25b1cf4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['ex', 'parrot']\n"
     ]
    }
   ],
   "source": [
    "s = 'ex-parrot'\n",
    "t = s.split('-')\n",
    "print(t)  # ['ex', 'parrot']"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6230163f",
   "metadata": {},
   "source": [
    "### `join()` Method\n",
    "\n",
    "If you have a list of strings, you can concatenate them into a single string using `join()`. Note that `join()` is a string method, so you invoke it on the delimiter and pass the list as an argument."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "95297ae8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'pining for the fjords'"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "delimiter = ' '\n",
    "t = ['pining', 'for', 'the', 'fjords']\n",
    "s = delimiter.join(t)\n",
    "s"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0fbe0382",
   "metadata": {},
   "source": [
    "In this case the delimiter is a space character, so `join` puts a space\n",
    "between words.\n",
    "To join strings without spaces, you can use the empty string, `''`, as a delimiter."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "cdf5cd28",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### EXERCISE: Using split() and join()\n",
    "# 1. Split the sentence \"Python is an amazing language\" into a list of words\n",
    "# 2. Split the string \"2026-02-16\" by the delimiter \"-\"\n",
    "# 3. Take the sentence \"Python programming is fun\", \n",
    "#    split it, \n",
    "#    reverse the list, and \n",
    "#    join back with \" - \"\n",
    "### Your code starts here:\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "01866617",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1. Words: ['Python', 'is', 'an', 'amazing', 'language']\n",
      "2. Date parts: ['2026', '02', '16']\n",
      "3. Reversed and joined: fun - is - programming - Python\n"
     ]
    }
   ],
   "source": [
    "# Solution\n",
    "# 1. Split sentence into words\n",
    "sentence = \"Python is an amazing language\"\n",
    "words = sentence.split()\n",
    "\n",
    "# 2. Split date string by delimiter\n",
    "date_string = \"2026-02-16\"\n",
    "date_parts = date_string.split(\"-\")\n",
    "\n",
    "# 3. Split, reverse, and join\n",
    "sentence2 = \"Python programming is fun\"\n",
    "words2 = sentence2.split()\n",
    "words2.reverse()\n",
    "result = \" - \".join(words2)\n",
    "\n",
    "print(f\"1. Words: {words}\")\n",
    "print(f\"2. Date parts: {date_parts}\")\n",
    "print(f\"3. Reversed and joined: {result}\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "6c64cc7a-ee3e-41e8-857e-2e5b69943945",
   "metadata": {},
   "source": [
    "## Nested Lists\n",
    "\n",
    "- Although a list can contain another list, the nested list still counts as a single element.\n",
    "- The elements of a list don't have to be the same data type. "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d7f6e6cf-f57a-4cab-8258-4b912c89fc2d",
   "metadata": {},
   "source": [
    "The following lists contain a string, a float, an integer, and another list (**nested**). We see that the length of the list `mixed_list` is 4, although it looks having more than 4 elements, but the 4th element is a list and counted only as 1 element."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "d9153b34-87ab-4044-a4e8-d4c87ad19f15",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['spam', 2.0, 5, [1, 2, 3, 4, 5]]\n",
      "There are 4 elements in the mixed list.\n"
     ]
    }
   ],
   "source": [
    "numbers = [1, 2, 3, 4, 5]\n",
    "mixed_list = ['spam', 2.0, 5, numbers ]\n",
    "\n",
    "print(mixed_list)\n",
    "print(f\"There are {len(mixed_list)} elements in the mixed list.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "615407c5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1, 2], [3, 4], [5, 6]]\n",
      "The nested list has 3 elements and they are lists themselves.\n"
     ]
    }
   ],
   "source": [
    "nested_list = [ \n",
    "               [1, 2], \n",
    "               [3, 4], \n",
    "               [5, 6]\n",
    "               ]\n",
    "print(nested_list)\n",
    "print(f\"The nested list has {len(nested_list)} elements and they are lists themselves.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "bc2a0fd8",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### EXERCISE: Working with Nested Lists\n",
    "matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n",
    "# 1. Access the second row (index 1)\n",
    "# 2. Access the element in the first row, third column (value should be 3)\n",
    "# 3. Calculate the total number of elements (not rows) using len()\n",
    "### Your code starts here:\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "66505057",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Second row: [4, 5, 6]\n",
      "Element at [0][2]: 3\n",
      "Total elements: 9\n"
     ]
    }
   ],
   "source": [
    "# Solution\n",
    "matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n",
    "second_row = matrix[1]\n",
    "element_1_3 = matrix[0][2]\n",
    "total_elements = len(matrix) * len(matrix[0])  # rows * cols\n",
    "\n",
    "print(f\"Second row: {second_row}\")\n",
    "print(f\"Element at [0][2]: {element_1_3}\")\n",
    "print(f\"Total elements: {total_elements}\")"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Tags",
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
