{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "56e251cd",
   "metadata": {},
   "source": [
    "# 02 — Structures et fonctions\n",
    "\n",
    "## Des objets Python aux données structurées"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "391c399d",
   "metadata": {},
   "source": [
    "Les Termes en ``saillance`` sont définis dans VOCABULAIRE.md"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "633d530a-f766-4461-bf5e-b494eb92d942",
   "metadata": {},
   "source": [
    "Connaître ses variables et ses structures : pourquoi ?\n",
    "\n",
    "Imaginons un exercice simple, j'ai des notes et je voudrais calculer une moyenne, les données pourraient se présenter de différentes manières."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1a5d18a6-7bf1-4cad-a35b-40b6202169fa",
   "metadata": {},
   "outputs": [],
   "source": [
    "#des variables individuelles :\n",
    "note1 = 12\n",
    "note2 = 15\n",
    "note3 = 17\n",
    "print((note1+note2+note3)/3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "839a0f57-666b-4464-b3a7-b8f3eaf489af",
   "metadata": {},
   "source": [
    "Imaginons que l'on ait 2 ou 3 fois plus de notes à traiter, le code serait 2 ou 3 fois plus long ... Avec une liste on rend tout ça plus souple"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "846173c2-1332-4d09-b600-2872e6dbfa20",
   "metadata": {},
   "outputs": [],
   "source": [
    "notes = [12,15,17]\n",
    "print(sum(notes)/3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a48727ce-129a-43d7-9610-911bd6529842",
   "metadata": {},
   "outputs": [],
   "source": [
    "#Et même en mieux :\n",
    "print(sum(notes)/len(notes))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "040a0ee3-26a6-4fd1-9029-a921aa9368a5",
   "metadata": {},
   "outputs": [],
   "source": [
    "#Ainsi on peut régler des listes de notes plus longues sans changer l'instruction\n",
    "notes = [12,15,17, 14, 8, 12, 9]\n",
    "print(sum(notes)/len(notes))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "533e8c66-c93c-47a3-aa86-def9286c5b8b",
   "metadata": {},
   "source": [
    "Imaginons que la liste comporte des notes entrées comme des chaînes de caractères, comment faire ?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9b4183ee-19df-4ac9-9bb9-53bfac2b4d0b",
   "metadata": {},
   "outputs": [],
   "source": [
    "notes = [12,15,\"17\", 14, \"8\", 12, \"9\"]\n",
    "#Essayez de calculer la moyenne sans changer les de données d'origine mais en créant une liste nettoyée\n",
    "#Recette possible : une liste vide, une boucle et la méthode append\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d27dcd99-c97f-4708-bad0-4f00fbfd5d9b",
   "metadata": {},
   "source": [
    "Un cas un peu plus difficile maintenant. On a aussi des cas particuliers à gérer :\n",
    "- si l'étudiant a une absence justifiée (ABJ), on ne compte rien\n",
    "- si par contre c'est une absence injustifiée (ABI), c'est un zéro\n",
    "\n",
    "A vous de jouer !"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8eaad940-0e8f-42b4-a46f-176beb191d94",
   "metadata": {},
   "outputs": [],
   "source": [
    "notes = [12,15, \"ABJ\",  14, 8, 12, 9,\"ABI\", \"16\"]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bc58835c",
   "metadata": {},
   "source": [
    "## 1. Choisir une structure de données"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b3ffcbf8",
   "metadata": {},
   "source": [
    "<div style=\"background:#f2ecff; border-left:6px solid #6f42c1; padding:12px 16px; border-radius:4px;\">\n",
    "<strong>Pourquoi est-ce utile ?</strong><br>La structure choisie exprime ce que l'on veut conserver : \n",
    "    \n",
    "    - ``list`` : la liste garde l'ordre\n",
    "    - ``set``  : l' ensemble produit le vocabulaire (les éléments uniques)\n",
    "    - ``dict`` : le dictionnaire associe des données (clé:valeur, mot: fréquence ....)\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "60c1d616",
   "metadata": {},
   "outputs": [],
   "source": [
    "tokens = [\"le\", \"chat\", \"dort\", \"le\"]       # ordre et doublons\n",
    "print(type(tokens))\n",
    "vocabulaire = set(tokens)                       # valeurs uniques\n",
    "print(type(vocabulaire))\n",
    "document = {\"titre\": \"Exemple\", \"langue\": \"fr\"}  # clé → valeur\n",
    "print(type(document))\n",
    "print(tokens, vocabulaire, document)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d5e9021",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Le choix de la structure change la question posée au texte\n",
    "texte = \"le chat voit le chien\"\n",
    "tokens = texte.split()\n",
    "print(\"Séquence :\", tokens)\n",
    "print(\"Vocabulaire :\", sorted(set(tokens)))\n",
    "print(\"Nombre d'occurrences / de types :\", len(tokens), len(set(tokens)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "78a47f86",
   "metadata": {},
   "source": [
    "<div style=\"background:#fff3e6; border-left:6px solid #c86400; padding:12px 16px; border-radius:4px;\">\n",
    "Comment trouver l’ensemble des catégories distinctes sans doublon ?\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6029b083",
   "metadata": {},
   "outputs": [],
   "source": [
    "categories = [\"blog\", \"institution\", \"blog\", \"recherche\", \"blog\", \"institution\", \"toto\"]\n",
    "# TODO"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7dc46263",
   "metadata": {},
   "source": [
    "## 2. Compter avec un dictionnaire"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "995207c3",
   "metadata": {},
   "source": [
    "<div style=\"background:#f2ecff; border-left:6px solid #6f42c1; padding:12px 16px; border-radius:4px;\">\n",
    "Un dictionnaire de fréquences relie chaque forme à son nombre d'occurrences. Cette représentation est la base des listes de mots fréquents par exemple\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9aa5545b",
   "metadata": {},
   "outputs": [],
   "source": [
    "tokens = \"le corpus contient le texte\".split()\n",
    "frequences = {}\n",
    "for token in tokens:\n",
    "    if token not in frequences:#on ne l'a pas encore vu\n",
    "        frequences[token] = 0\n",
    "    frequences[token] += 1#on ajoute une occurrence\n",
    "    print(frequences)\n",
    "print(\"dictionnaire final:\")\n",
    "print(frequences)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "516b1870",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exemple : comparer rapidement deux mini-textes\n",
    "textes = [\"langue corpus langue\", \"python corpus données\"]\n",
    "for texte in textes:\n",
    "    frequences_texte = {}\n",
    "    for token in texte.split():\n",
    "        frequences_texte[token] = frequences_texte.get(token, 0) + 1\n",
    "    print(frequences_texte)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a23db35a",
   "metadata": {},
   "source": [
    "<div style=\"background:#fff3e6; border-left:6px solid #c86400; padding:12px 16px; border-radius:4px;\">\n",
    "<strong>À vous de jouer</strong><br>Comptez les documents par langue à partir de la liste de dictionnaires.\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "878e0fe1",
   "metadata": {},
   "outputs": [],
   "source": [
    "documents = [\n",
    "    {\"titre\": \"A\", \"langue\": \"fr\"},\n",
    "    {\"titre\": \"B\", \"langue\": \"en\"},\n",
    "    {\"titre\": \"C\", \"langue\": \"fr\"},\n",
    "]\n",
    "effectifs = {}#devra associer à chaque langue le nombre de documents\n",
    "# TODO"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4cd70db6",
   "metadata": {},
   "source": [
    "## 3. Parcourir une structure imbriquée"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dd96bd06",
   "metadata": {},
   "source": [
    "<div style=\"background:#f2ecff; border-left:6px solid #6f42c1; padding:12px 16px; border-radius:4px;\">\n",
    "<strong>Pourquoi est-ce utile ?</strong><br>Les corpus sont rarement de simples listes de chaînes : un document peut avoir plusieurs auteurs, mots-clés et dates. Les structures imbriquées permettent de représenter cette richesse et correspondent directement au format JSON que vous verrez mercredi/jeudi.\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "44f23ade",
   "metadata": {},
   "outputs": [],
   "source": [
    "mediatheque = {\n",
    "    \"nom\": \"Bibliothèque SHS\",\n",
    "    \"documents\": [\n",
    "        {\"titre\": \"Méthodes\", \"auteurs\": [\"A. Martin\"], \"disponible\": True},\n",
    "        {\"titre\": \"Corpus\", \"auteurs\": [\"L. Diallo\", \"S. Roy\"], \"disponible\": False},\n",
    "    ],\n",
    "}\n",
    "print(mediatheque[\"documents\"][1][\"auteurs\"][0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "41720348",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exemple : revenir aux textes grâce aux métadonnées\n",
    "corpus_annote = {\n",
    "    \"documents\": [\n",
    "        {\"id\": \"d1\", \"texte\": \"Nous proposons une méthode.\", \"genre\": \"article\"},\n",
    "        {\"id\": \"d2\", \"texte\": \"Bienvenue dans la formation.\", \"genre\": \"institution\"},\n",
    "    ]\n",
    "}\n",
    "for document in corpus_annote[\"documents\"]:\n",
    "    print(document[\"id\"], document[\"genre\"], \"→\", document[\"texte\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8c19c453",
   "metadata": {},
   "source": [
    "<div style=\"background:#fff3e6; border-left:6px solid #c86400; padding:12px 16px; border-radius:4px;\">\n",
    "Construisez une liste contenant seulement le titre des documents disponibles de mediatheque.\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d5a39715",
   "metadata": {},
   "outputs": [],
   "source": [
    "titres_disponibles = []\n",
    "# TODO"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d4c9bcd8",
   "metadata": {},
   "source": [
    "## 4. Factoriser avec des fonctions"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fef9c8c7",
   "metadata": {},
   "source": [
    "<div style=\"background:#f2ecff; border-left:6px solid #6f42c1; padding:12px 16px; border-radius:4px;\">\n",
    "<strong>Pourquoi est-ce utile ?</strong><br>Copier-coller le code a ses limites, ça prend de la place et quand on veut faire une modification sur un code dupliqué 10 fois, on doit intervenir 10 fois.\n",
    "    \n",
    " Une fonction vise à regrouper sous un nom uen série d'opérations et facilite reproductibilité et maintenance.\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "85e4291a",
   "metadata": {},
   "outputs": [],
   "source": [
    "def nettoyer_texte(texte):\n",
    "    texte = texte.lower()\n",
    "    return texte\n",
    "\n",
    "print(nettoyer_texte(\"Bonjour Corpus\"))\n",
    "print(nettoyer_texte(\"Bienvenue dans la formation\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "33f29a47",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exemple : le même nettoyage appliqué à tout un corpus\n",
    "corpus_brut = [\"  Premier TEXTE \", \"Deuxième texte  \", \"  TROISIÈME texte\"]\n",
    "corpus_propre = [nettoyer_texte(texte) for texte in corpus_brut]\n",
    "print(corpus_propre)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c5099a14",
   "metadata": {},
   "source": [
    "<div style=\"background:#fff3e6; border-left:6px solid #c86400; padding:12px 16px; border-radius:4px;\">\n",
    "<strong>À vous de jouer</strong><br>Écrivez `decrire_texte(texte)` qui renvoie un dictionnaire avec `caracteres`, `mots` et `types` (nombre de mots distincts en minuscules).\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4263e9de",
   "metadata": {},
   "outputs": [],
   "source": [
    "def decrire_texte(texte):\n",
    "    # TODO\n",
    "    pass"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "94c95c83",
   "metadata": {},
   "source": [
    "## 5. Gérer une valeur invalide"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0b1081a1",
   "metadata": {},
   "source": [
    "<div style=\"background:#f2ecff; border-left:6px solid #6f42c1; padding:12px 16px; border-radius:4px;\">\n",
    "<strong>Pourquoi est-ce utile ?</strong><br>Les données réelles contiennent des cellules vides, <code>inconnu</code> ou des valeurs mal saisies. Une gestion ciblée des exceptions permet de conserver les autres documents, tout en rendant l'anomalie explicite.\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c7bdf524",
   "metadata": {},
   "outputs": [],
   "source": [
    "def convertir_entier(valeur):\n",
    "    try:\n",
    "        return int(valeur)\n",
    "    except (TypeError, ValueError):\n",
    "        return f\"on ne peut pas convertir '{valeur}'\"\n",
    "\n",
    "print(convertir_entier(\"24\"))\n",
    "print(convertir_entier(\"inconnu\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1c9faaf9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exemple : convertir des années sans perdre tout le corpus\n",
    "documents = [\n",
    "    {\"titre\": \"A\", \"annee\": \"2021\"},\n",
    "    {\"titre\": \"B\", \"annee\": \"inconnue\"},\n",
    "    {\"titre\": \"C\", \"annee\": \"2024 \"},\n",
    "]\n",
    "for document in documents:\n",
    "    document[\"annee_num\"] = convertir_entier(document[\"annee\"])#annee_num contiendra l'année sous forme d'entier\n",
    "print(documents)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a8bb0288",
   "metadata": {},
   "source": [
    "<div style=\"background:#fff3e6; border-left:6px solid #c86400; padding:12px 16px; border-radius:4px;\">\n",
    "Complétez la fonction `moyenne_valide(valeurs)` qui calcule la moyenne pour les 2 séries de notes\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d2851806",
   "metadata": {},
   "outputs": [],
   "source": [
    "def moyenne_valide(valeurs):\n",
    "    # TODO: calculer la moyenne des données de valeurs et stocker dans une variable nommée 'moyenne'\n",
    "    return moyenne\n",
    "serie1 =  [12,15,\"17\", 14, \"8\", 12, \"9\"]\n",
    "serie2 =  [5, 2, \"15\", 18, \"6\", \"0\", 17]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2d313268",
   "metadata": {},
   "source": [
    "## 6. Persistence\n",
    "\n",
    "Observer la différence entre deux manières de copier une liste"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a0ff18c3-3abd-413e-986a-8ac1a0e9af7c",
   "metadata": {},
   "outputs": [],
   "source": [
    "toto = [13, 12, 8]\n",
    "titi = toto\n",
    "print(titi)\n",
    "titi.append(14)\n",
    "print(titi)\n",
    "print(toto)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "41041e97-924d-4789-ba7e-ec486e5b2311",
   "metadata": {},
   "outputs": [],
   "source": [
    "toto = [13, 12, 8]\n",
    "titi = toto.copy()\n",
    "print(titi)\n",
    "titi.append(14)\n",
    "print(titi)\n",
    "print(toto)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "681d5fc5-f0e8-4f5d-af90-50ff90bbdd51",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.10.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
