{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "e0b8ff01",
   "metadata": {
    "tags": [
     "list",
     "indexing",
     "slicing"
    ]
   },
   "source": [
    "# Accessing List Elements\n",
    "\n",
    "Now that we know how to create lists, let's learn how to access and extract data from them. Python provides several ways to retrieve elements from a list.\n",
    "\n",
    "- Understanding List Indices\n",
    "  Lists in Python use **zero-based indexing**, meaning the first element is at position `0`, the second at position `1`, and so on. You can think of the index as the offset from the beginning of the list.\n",
    "- List Index Properties\n",
    "  List indices work the same way as string indices:\n",
    "    -   Any integer expression can be used as an index.\n",
    "    -   If you try to read or write an element that does not exist, you get an `IndexError`.\n",
    "    -   If an index has a negative value, it counts backward from the end of the list, starting with `-1`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "49df9200",
   "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": "85098893",
   "metadata": {},
   "source": [
    "Below, we look at **indexing** (accessing a single element) and **slicing** (accessing a sublist) separately."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c10a709f",
   "metadata": {},
   "source": [
    "## Indexing\n",
    "\n",
    "Indexing reads or writes a single element of a list using the **bracket operator**.\n",
    "\n",
    "- **Syntax**: `lst[index]`\n",
    "\n",
    "- Indices are 0-based: the first element is at index `0`.\n",
    "- Negative indices count from the end: `-1` is the last element, `-2` is the one before that.\n",
    "\n",
    "For example, if we have `fruits = ['apple', 'banana', 'cherry']`, then `fruits[0]` returns `'apple'` and `fruits[-1]` returns `'cherry'`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "789cafa2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "First: apple, Last: elderberry\n"
     ]
    }
   ],
   "source": [
    "fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry']\n",
    "first = fruits[0]\n",
    "last = fruits[-1]\n",
    "\n",
    "print(f\"First: {first}, Last: {last}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e0fc56a5",
   "metadata": {},
   "source": [
    "## Slicing\n",
    "\n",
    "Slicing works with **subsequences** of a list using the syntax: \n",
    "\n",
    "`lst[start:stop]`, or \n",
    "\n",
    "`lst[start:stop:step]`.\n",
    "\n",
    "- `start` is the index where the slice begins (inclusive).\n",
    "- `stop` is the index where the slice ends (exclusive).\n",
    "- `step` controls how many positions to advance (defaults to `1`). Use `2` to skip every other element, `-1` to reverse.\n",
    "- If `start` is omitted, Python starts from the beginning of the list.\n",
    "- If `stop` is omitted, Python slices all the way to the end of the list.\n",
    "- Slicing does not modify the original list; it returns a **new list** containing the selected elements."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "3d4beed3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Middle three: ['banana', 'cherry', 'date']\n",
      "From start: ['apple', 'banana', 'cherry']\n",
      "To end: ['cherry', 'date', 'elderberry']\n",
      "Every other: ['apple', 'cherry', 'elderberry']\n",
      "Reversed: ['elderberry', 'date', 'cherry', 'banana', 'apple']\n"
     ]
    }
   ],
   "source": [
    "fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry']\n",
    "\n",
    "middle_three = fruits[1:4]      # elements at indices 1, 2, 3\n",
    "from_start = fruits[:3]         # first three elements\n",
    "to_end = fruits[2:]             # from index 2 to end\n",
    "every_other = fruits[::2]       # step=2: every second element\n",
    "reversed_fruits = fruits[::-1]  # step=-1: reverses the list\n",
    "\n",
    "print(f\"Middle three: {middle_three}\")\n",
    "print(f\"From start: {from_start}\")\n",
    "print(f\"To end: {to_end}\")\n",
    "print(f\"Every other: {every_other}\")\n",
    "print(f\"Reversed: {reversed_fruits}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7072b4d2-c642-47f3-846f-4c71a654fe4a",
   "metadata": {},
   "source": [
    "The step parameter in slicing enables powerful patterns like skipping elements, reversing, and extracting at intervals:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "step-example-1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Every other: [0, 2, 4, 6, 8]\n",
      "Every third: [0, 3, 6, 9]\n",
      "Reversed: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]\n",
      "Every other, reversed: [9, 7, 5, 3, 1]\n",
      "Slice from 1 to 8, step 2: [1, 3, 5, 7]\n",
      "Backwards from 7 to 2: [7, 6, 5, 4, 3]\n"
     ]
    }
   ],
   "source": [
    "numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
    "\n",
    "print(f\"Every other: {numbers[::2]}\")\n",
    "print(f\"Every third: {numbers[::3]}\")\n",
    "print(f\"Reversed: {numbers[::-1]}\")\n",
    "print(f\"Every other, reversed: {numbers[::-2]}\")\n",
    "print(f\"Slice from 1 to 8, step 2: {numbers[1:8:2]}\")\n",
    "print(f\"Backwards from 7 to 2: {numbers[7:2:-1]}\")     ### reversing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "c679966e",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### EXERCISE: Indexing and Slicing Practice\n",
    "fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry', 'fig']\n",
    "# 1. Get the third element (index 2)\n",
    "# 2. Get the last element using negative indexing\n",
    "# 3. Get a slice of elements from index 1 to 4 (not including 4)\n",
    "# 4. Get every other element\n",
    "### Your code starts here:\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "80a003df",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Third element: cherry\n",
      "Last element: fig\n",
      "Slice [1:4]: ['banana', 'cherry', 'date']\n",
      "Every other: ['apple', 'cherry', 'elderberry']\n"
     ]
    }
   ],
   "source": [
    "# Solution\n",
    "fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry', 'fig']\n",
    "third = fruits[2]\n",
    "last = fruits[-1]\n",
    "slice_1_to_4 = fruits[1:4]\n",
    "every_other = fruits[::2]\n",
    "\n",
    "print(f\"Third element: {third}\")\n",
    "print(f\"Last element: {last}\")\n",
    "print(f\"Slice [1:4]: {slice_1_to_4}\")\n",
    "print(f\"Every other: {every_other}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5ba6d2cf",
   "metadata": {},
   "source": [
    "## Query Methods\n",
    "\n",
    "These methods help you find information about elements in a list without modifying it.\n",
    "- `.count()`\n",
    "- `.index()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "f3efa52e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The number 2 appears 3 times\n",
      "First 'b' is at index: 1\n"
     ]
    }
   ],
   "source": [
    "# count() - Returns number of times element appears\n",
    "numbers = [1, 2, 3, 2, 4, 2, 5]\n",
    "count = numbers.count(2)\n",
    "print(f\"The number 2 appears {count} times\")\n",
    "\n",
    "# index() - Returns index of first occurrence\n",
    "letters = ['a', 'b', 'c', 'b', 'd']\n",
    "position = letters.index('b')\n",
    "print(f\"First 'b' is at index: {position}\")"
   ]
  }
 ],
 "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
}
