{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Erweiterte Datentypen: Container"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Listen und Tupel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[5, 10, 20, 30, 50]\n",
      "[0.5, 0.6, 0.8, 1.0, 1.2]\n",
      "['Joe', 'Alice', 'Bob', 'Charly']\n",
      "[1, 'Joe', 1.4, 'Alice', 100]\n",
      "['one'] [] []\n"
     ]
    }
   ],
   "source": [
    "# Listenliterale\n",
    "\n",
    "values = [5, 10, 20, 30, 50]\n",
    "print(values)\n",
    "fractions = [0.5, 0.6, 0.8, 1.0, 1.2]\n",
    "print(fractions)\n",
    "names = [\"Joe\", \"Alice\", \"Bob\", \"Charly\"]\n",
    "print(names)\n",
    "heap = [1, \"Joe\", 1.4, \"Alice\", 100]\n",
    "print(heap)\n",
    "single = [\"one\"]\n",
    "leer = []\n",
    "auch_leer = list()\n",
    "print(single, leer, auch_leer)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(5, 10, 20, 30, 50)\n",
      "(0.5, 0.6, 0.8, 1.0, 1.2)\n",
      "('Joe', 'Alice', 'Bob', 'Charly')\n",
      "(1, 'Joe', 1.4, 'Alice', 100)\n",
      "('one',) ('one',) () ()\n"
     ]
    }
   ],
   "source": [
    "# Tuplelliterale\n",
    "values = (5, 10, 20, 30, 50)\n",
    "print(values)\n",
    "fractions = (0.5, 0.6, 0.8, 1.0, 1.2)\n",
    "print(fractions)\n",
    "names = (\"Joe\", \"Alice\", \"Bob\", \"Charly\")\n",
    "print(names)\n",
    "heap = (1, \"Joe\", 1.4, \"Alice\", 100)\n",
    "print(heap)\n",
    "t_single = (\"one\",)\n",
    "t_auch_single = \"one\",\n",
    "t_leer = ()\n",
    "t_auch_leer = tuple()\n",
    "print(t_single, t_auch_single, t_leer, t_auch_leer)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4, 5] (1, 2, 3, 4, 5)\n",
      "[10, 20, 30, 40, 50] (1, 2, 3, 4, 5)\n",
      "[1, 2, 3, 4, 5]\n"
     ]
    }
   ],
   "source": [
    "# Umwandlung\n",
    "\n",
    "l = [1, 2, 3, 4, 5]\n",
    "t = tuple(l)\n",
    "print(l, t)\n",
    "l = [10, 20, 30, 40, 50]\n",
    "print(l, t)\n",
    "l2 = list(t)\n",
    "print(l2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['h', 'a', 'l', 'l', 'o']\n",
      "('h', 'a', 'l', 'l', 'o')\n"
     ]
    }
   ],
   "source": [
    "s = \"hallo\"\n",
    "print(list(s))\n",
    "print(tuple(s))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Indizierung"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Frühling\n",
      "Herbst\n",
      "Winter\n",
      "Sommer\n"
     ]
    }
   ],
   "source": [
    "seasons = [\"Frühling\", \"Sommer\", \"Herbst\", \"Winter\"]\n",
    "print(seasons[0])   # Erstes Element hat Index 0!\n",
    "print(seasons[2])\n",
    "print(seasons[-1])  # Negative Indices zählen vom letzten Element rückwärts\n",
    "print(seasons[-3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "ename": "IndexError",
     "evalue": "list index out of range",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mIndexError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[1;32m/home/chris/work/python-kurs-softed/notebooks/containertypes.ipynb Cell 9\u001b[0m line \u001b[0;36m2\n\u001b[1;32m      <a href='vscode-notebook-cell:/home/chris/work/python-kurs-softed/notebooks/containertypes.ipynb#X11sZmlsZQ%3D%3D?line=0'>1</a>\u001b[0m \u001b[39m# Ungültige Indizes führen zu einem Fehler (IndexError Exception)\u001b[39;00m\n\u001b[0;32m----> <a href='vscode-notebook-cell:/home/chris/work/python-kurs-softed/notebooks/containertypes.ipynb#X11sZmlsZQ%3D%3D?line=1'>2</a>\u001b[0m \u001b[39mprint\u001b[39m(seasons[\u001b[39m4\u001b[39;49m])  \u001b[39m# 4 Elemente => gültige Indizes 0..3\u001b[39;00m\n",
      "\u001b[0;31mIndexError\u001b[0m: list index out of range"
     ]
    }
   ],
   "source": [
    "# Ungültige Indizes führen zu einem Fehler (IndexError Exception)\n",
    "print(seasons[4])  # 4 Elemente => gültige Indizes 0..3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Ebenso\n",
    "print(seasons[-5])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Zuweisung an einzelne Listenelemente\n",
    "\n",
    "l = [1, 2, 3, 4, 5]\n",
    "l[1] = -1\n",
    "print(l)\n",
    "l[3] = \"vier\"\n",
    "print(l)\n",
    "l[-1] = 5.0\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Indizierung funktioniert auch mit Tupeln mit der selben Syntax\n",
    "t = (1, 2, 3, 4, 5)\n",
    "print(t[0], t[-2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Aber Tuple sind nicht-veränderbar (immutable)\n",
    "\n",
    "t[2] = \"drei\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Slicing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "l = list(range(10))  # l = [0, 1, ..., 9]\n",
    "print(l)\n",
    "print(l[2:4])  # Start ist inklusiv, Ende nicht!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Auch wenn kein oder nur ein Element \"übrig bleibt\", ist das Ergebnis eine Liste\n",
    "\n",
    "print(l[2:3])\n",
    "print(l[9:-1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Start und End können leer, also \"offen\", sein\n",
    "\n",
    "print(l[5:])\n",
    "print(l[:3])  # auch hier ist der Ende-Index nicht-inklusiv!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Sind Start und Ende leer, ist das Ergebnis eine Kopie der Liste / des Tuples\n",
    "\n",
    "l1 = [1, 2, 3]\n",
    "l2 = l1[:]\n",
    "l3 = l1\n",
    "l1[0] = 999\n",
    "print(l1)\n",
    "print(l2)\n",
    "print(l3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Zuweisung an Listenslices ist möglich!\n",
    "\n",
    "seasons = [\"Winter\", \"Frühling\", \"Sommer\", \"Herbst\"]\n",
    "seasons[1:1] = [\"Karneval\"]\n",
    "print(seasons)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Listen oder Tuples können mit + zu einer/m neuen Liste / Tupel zusamengefügt werden \n",
    "\n",
    "items = [1, 2, 3]\n",
    "more_items = items + [\"one\", \"two\", \"three\"]\n",
    "print(more_items)\n",
    "items[1:2] = []\n",
    "print(items)\n",
    "print(more_items)\n",
    "more_items += [4, 6, 6]\n",
    "print(more_items)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "t = (1, 2, 3)\n",
    "t2 = t + (4, 5, 6)\n",
    "print(t)\n",
    "print(t2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Achtung: \n",
    "\n",
    "t = (1, 2, 3)\n",
    "t2 = t\n",
    "print(t)\n",
    "print(t2)\n",
    "print(t is t2)\n",
    "t += (1, 2, 3)   # Tuples sind immutable, t ist eine neue Kopie!\n",
    "print(t)\n",
    "print(t2)\n",
    "print(t is t2)\n",
    "s = \"ein string\"\n",
    "s += \" und noch mehr\"\n",
    "i = 0\n",
    "i += 1\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "l = list(range(10))\n",
    "import sys\n",
    "sys.getsizeof(l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Dictionaries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Auch Hashtables, Lookup Tables usw. genannt\n",
    "# Tabellen mit Zurdnung von Schlüsseln zu werten (Key-value pairs)\n",
    "\n",
    "d = {}\n",
    "# oder:\n",
    "d = dict()\n",
    "print(d)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scores = {\n",
    "    \"blue team\": 40,\n",
    "    \"green team\": 45,\n",
    "    \"red team\": 30,\n",
    "    \"black team\": 60\n",
    "}\n",
    "print(scores)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Look up\n",
    "\n",
    "print(\"The red team scored:\", scores[\"red team\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Neue Key/Value Paare hinzufügen (Dictionaries sind veränderbar!)\n",
    "\n",
    "scores[\"white team\"] = 45\n",
    "scores[\"rainbow team\"] = 50\n",
    "print(scores)\n",
    "del scores[\"blue team\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Umwandlung\n",
    "\n",
    "print(tuple(scores))  # Tupel der Keys\n",
    "\n",
    "print(list(scores))  # Liste der Keys\n",
    "\n",
    "print(tuple(scores.keys()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Iteration\n",
    "\n",
    "for key in scores:\n",
    "    print(\"Das\", key, \"hat\", scores[key], \"Punkte.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Iteration über Key/Value Paare\n",
    "\n",
    "print(scores.items())\n",
    "\n",
    "for key, value in scores.items():\n",
    "    print(\"Das\", key, \"hat\", value, \"Punkte.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Keys müssen keine Strings, aber immutable sein\n",
    "# => Integers, Floats, Tuples sind ok\n",
    "\n",
    "numbers = {1: \"one\", 2: \"two\", 3: \"three\"}\n",
    "print(numbers[2])  # Achtung: nicht mit Listenindex verwechseln!\n",
    "\n",
    "pixels = {\n",
    "    (0, 5): 'r',\n",
    "    (2, 7): 'b', \n",
    "    (3, 10): 'r',\n",
    "    (5, 2): 'g',\n",
    "    (5, 5): 'b', \n",
    "}\n",
    "\n",
    "for row in range(6):\n",
    "    for col in range(10):\n",
    "        value = pixels.get((row, col), \".\")\n",
    "        print(value, end=\"\")\n",
    "    print()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Sets (Mengen)\n",
    "\n",
    "Mengen sind wie unsortierte Tupel, in denen jedes Element nur einmal vorkommen kann."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "s = set([])\n",
    "print(s)   # leeres Set wird repräsentiert mit 'set()', nicht '{}' (leeres Dictionary!)\n",
    "\n",
    "s2 = set([2,3,5])\n",
    "s2.add(4)\n",
    "s2.add(5)  # Schon im Set enthalten\n",
    "print(s2)\n",
    "\n",
    "for i in s2:\n",
    "    print(i)\n",
    "\n",
    "print()\n",
    "\n",
    "s2.add(1)\n",
    "s2.remove(4)\n",
    "\n",
    "for i in s2:\n",
    "    print(i)   # Reihenfolge nach Änderung nicht garantiert gleich!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Kombination\n",
    "\n",
    "s1 = set([1, 2, 3, 5])\n",
    "s2 = set([4, 5, 6, 7])\n",
    "\n",
    "# Union (alle Elemente aus beiden Sets)\n",
    "print(s1 | s2)\n",
    "\n",
    "# Intersection (alle Elemente, die sowohl in s1 als auch s2 sind)\n",
    "print(s1 & s2)\n",
    "\n",
    "# Difference (alle Elemente in s1, die nicht auch in s2 sin)\n",
    "print(s1 - s2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Siehe: https://docs.python.org/3/library/stdtypes.html#set-types-set-frozenset"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "softed",
   "language": "python",
   "name": "softed"
  },
  "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.11.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
