\chapter{Types construits}

\section{Les listes}

\begin{exointro}{\null}
On considère la matrice :
\[
A=\begin{pmatrix}-3 & 1 & 0\\1 & -1 & 2\\0 & -3 & 5\end{pmatrix}.
\]
\begin{questions}
\item Créer une liste nommée \texttt{a} représentant la matrice $A$.

\item \'Ecrire une fonction \texttt{valabs(liste)} qui retourne une liste composée des items de la liste \texttt{liste} sans leur signe.

\textit{Aide : on pourra utiliser la fonction \texttt{abs(x)} qui donne la valeur absolue du nombre $x$ (c'est-à-dire la valeur de $x$ sans son signe)}.

\item À l'aide de la fonction \texttt{valabs(liste)}, construire une liste \texttt{b} par compréhension représentant une matrice dont tous les coefficients sont égaux à ceux de $A$ sans leur signe.

\item Créer une fonction \texttt{somme(matrice)} qui calcule la somme des coefficients d'une matrice.
\end{questions}
\vspace*{-1em}
\end{exointro}


\subsection{Définitions}

\begin{defins}
Une \textit{liste} est une variable dans laquelle peuvent être stockées plusieurs valeurs, appelées les \textit{items} de la liste.
\end{defins}

\begin{Remarque}
le mot \textit{item} est masculin.
\end{Remarque}

\begin{Exemples}
\begin{itemize}
\item On souhaite que la variable \texttt{villes} contiennent plusieurs villes de France. En Python, on peut la définir par exemple ainsi :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
villes = ["Bordeaux","Paris","Marseille","Lyon","Nantes"]
\end{tabularx}

\item On souhaite que la variable \texttt{ages} contiennent plusieurs valeurs numériques. On peut alors procéder ainsi :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
ages = [10,11,12,13,14,15,16,17,18]
\end{tabularx}
\end{itemize}
\end{Exemples}

\subsection{Opérations sur les items d'une liste}

\subsubsection{Créer une liste à items identiques}

Pour créer une liste ne comprenant que des items prenant la même valeur, on utilise la syntaxe :
\begin{center}
\texttt{liste = [<valeur>]*<nombre d'items souhaités>}
\end{center}

\begin{Exemples}
\begin{itemize}
\item L'instruction suivante créée une liste de 10 items prenant tous la valeur 0.

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
liste = [0]*10
\end{tabularx}

\item L'instruction suivante créée la liste \texttt{[1,2,1,2,1,2,1,2,1,2]}.

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
[1,2]*5
\end{tabularx}
\end{itemize}
\end{Exemples}

\subsubsection{Afficher un item}

Comme pour les chaînes de caractères, la numérotation (ou l'\textit{indexation}) des items commence à 0.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
villes = ["Bordeaux","Paris","Marseille","Lyon","Nantes"]\\
print(villes[0])
\end{tabularx}

\Par

Ce programme affiche le premier item, à savoir ici : \og Bordeaux \fg.
\end{Exemple}

\subsubsection{Modifier un item}

Si on souhaite modifier la valeur d'un item, il suffit de le remplacer directement à l'aide de son index.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
villes[4] = 'Bourg-en-Bresse'
\end{tabularx}

\Par

Ici, le cinquième item de la liste \texttt{villes}, qui était \og Nantes \fg, a été remplacé par une autre valeur, à savoir ici : \og Bourg-en-Bresse \fg.
\end{Exemple}

\subsubsection{Supprimer un item}

Il existe deux manières de supprimer un item en Python, comme le montrent les exemples suivants.

\begin{Exemples}
\begin{itemize}
\item Avec la commande \texttt{del} (avec l'index de l'item) :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
del villes[4] (efface l'item d'index 5)
\end{tabularx}


\item Avec la méthode \texttt{remove} (avec la valeur de l'item) :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
villes.remove("Paris")
\end{tabularx}
\end{itemize}
\end{Exemples}

\subsubsection{Inverser les items}

On peut inverser l'ordre des items dans une liste à l'aide de la méthode \texttt{reverse}.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
villes = ["Bordeaux","Paris","Marseille","Lyon","Nantes"]\\
villes.reverse()\\
print(villes)
\end{tabularx}

\Par

Le programme affiche alors : 

\Par

\begin{center}
\texttt{['Nantes', 'Lyon', 'Marseille', 'Paris', 'Bordeaux']}\end{center}
\end{Exemple}


\subsubsection{Compter le nombre d'items}
\label{fonction-len-liste}

On peut compter le nombre d'items dans une liste à l'aide de la fonction \texttt{len}, déjà rencontrée dans le chapitre précédent, page \pageref{fonction-len-chaine}.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
villes = ['Grenoble', 'Nantes', 'Lyon', 'Marseille', 'Paris']\\
print(len(villes))
\end{tabularx}

\Par

Ce programme nous renvoie la valeur \texttt{5}, car il y a 5 items dans la liste.
\end{Exemple}

\subsubsection{Compter les occurrences d'une valeur}

Si on souhaite savoir combien de fois un item apparaît dans une liste, on peut utiliser la méthode \texttt{count}.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
maliste = ['Jean', 'Pierre', 'Jean', 'Paul', 'Lucie']\\
maliste.count('Jean')
\end{tabularx}

\Par

Ce programme affiche \og 2 \fg{} car \og Jean \fg{} apparaît deux fois dans la liste.
\end{Exemple}

\subsubsection{Trouver l'index d'un item}

Dans une liste volumineuse, il est souvent utile de faire appel à la méthode \texttt{index} pour trouver un item bien particulier.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
valeurs = ['120','48','75','84','145','121','78','49']\\
valeurs.index('121')
\end{tabularx}

\Par

Ce programme affiche l'index de l'item \og 121 \fg, donc il affiche ici : \og 5 \fg.
\end{Exemple}

Si on ne souhaite pas connaître l'index de l'item, mais que l'on souhaite savoir si l'index est bien présent dans la liste, on peut utiliser le mot clé \texttt{in}, dont nous avions parlé à la page \pageref{mot-cle-in}.\label{mot-cle-InPourListe}

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
valeurs = ['120','48','75','84','145','121','78','49']\\
if ('121' in valeurs):\\
\hspace*{1cm}print('Ok !')
\end{tabularx}

\Par

Ce programme retourne \og \texttt{Ok !} \fg car la valeur a été trouvée dans la liste.
\end{Exemple}

\subsection{Manipulation des listes}

\subsubsection{Vider une liste}

On vide une liste ainsi :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
villes = []
\end{tabularx}


\subsubsection{Trier une liste}

On trie dans l'ordre alphabétique une liste avec la méthode \texttt{sort} :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
maliste = ['Jean', 'Pierre', 'Alexine', 'Paul', 'Lucie']\\
maliste.sort()\\
print(maliste)
\end{tabularx}

\Par

Le programme affiche :
\begin{center}
\texttt{['Alexine', 'Jean', 'Lucie', 'Paul', 'Pierre']}
\end{center}

\subsubsection{Afficher une partie d'une liste}

On peut afficher un certain nombre d'items depuis le début d'une liste ainsi :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
maliste = ['Jean', 'Pierre', 'Alexine', 'Paul', 'Lucie']\\
print(maliste[:2])
\end{tabularx}

\newpage

Le programme affiche :

\begin{center}
\texttt{['Jean', 'Pierre']}
\end{center}

Mais on peut aussi afficher les valeurs des items d'une liste à partir de n'importe quel rang :

\Par
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
maliste = ['Jean', 'Pierre', 'Alexine', 'Paul', 'Lucie']\\
print(maliste[2:4])
\end{tabularx}

\Par

Le programme affiche :

\begin{center}
\texttt{['Alexine', 'Paul']}
\end{center}

\begin{attention}
L'instruction \texttt{maliste[n:p]} affiche les items depuis l'index \texttt{n} jusqu'à l'item d'index \texttt{p-1}.
\end{attention}



\subsubsection{Dupliquer une liste}

Si on souhaite dupliquer une liste \texttt{villes} dans une autre liste \texttt{towns}, un simple \og = \fg{} suffit. Mais dans ce cas, les deux listes seront dépendantes, c'est-à-dire que si on modifie l'une d'elles (en y ajoutant par exemple un item), l'autre changera de la même façon.

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
villes = ['Bordeaux','Paris']\\
towns = villes\\
towns.append('Lens')\\
print(villes)
\end{tabularx}

\Par

Ce programme affiche :
\begin{center}
\texttt{['Bordeaux', 'Paris', 'Lens']}
\end{center}
contre toute attente car nous avons modifié la liste \texttt{towns}, et non la liste \texttt{villes} affichée.

\Par

Pour créer deux listes indépendantes, on utilisera la syntaxe suivante :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
villes = ['Bordeaux','Paris']\\
towns = villes[:]\\
towns[1]('Lens')\\
print(villes)\\
print(towns)
\end{tabularx}

\Par

Ce programme affiche :
\begin{center}
\texttt{['Bordeaux', 'Paris']}

\texttt{['Bordeaux', 'Lens']}
\end{center}

preuve que les deux listes sont indépendantes.

\subsubsection{Transformer une liste en chaîne de caractères}

La méthode \texttt{join} permet de transformer une liste en chaîne de caractères, en insérant (si besoin est) un caractère entre chaque item.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
villes = ['Bordeaux','Paris','Lyon']\\
itineraire = " - ".join(villes)\\
print(itineraire)
\end{tabularx}

\Par

Le programme affiche : 
\begin{center}
\texttt{'Bordeaux - Paris - Lyon'}
\end{center}
\end{Exemple}

\subsubsection{Transformer une chaîne de caractères en liste}

Ceci est possible avec la méthode \texttt{split}.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
villes = 'Bordeaux,Paris,Lens,Grenoble,Biarritz'\\
liste = villes.split(',')\\
print(liste)
\end{tabularx}

\Par

Le programme affiche :
\begin{center}
\texttt{['Bordeaux', 'Paris', 'Lens', 'Grenoble', 'Biarritz']}
\end{center}
\end{Exemple}


\subsubsection{Concaténer deux listes}

On peut concaténer deux listes avec les méthodes \texttt{append} ou \texttt{extend}.

\subsectionnn{Avec extend}

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
villes = ['Bordeaux', 'Paris', 'Lens', 'Grenoble']\\
villes\verb+_+espagne = ['Barcelone','Pampelune','Ibiza']\\
villes.extend(villes\verb+_+espagne)\\
villes
\end{tabularx}

\Par


Le programme affiche :

\Par

\begin{center}
\texttt{['Bordeaux', 'Paris', 'Lens', 'Grenoble', 'Barcelone', 'Pampelune', 'Ibiza']}
\end{center}
\end{Exemple}

\newpage

\subsectionnn{Avec append}

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
villes = ['Bordeaux', 'Paris', 'Lens', 'Grenoble', 'Biarritz']\\
villes\verb+_+espagne = ['Barcelone','Pampelune','Ibiza']\\
villes.append(villes\verb+_+espagne)\\
villes
\end{tabularx}

\Par

Le programme affiche :

\Par

\begin{center}
\ttfamily
['Bordeaux', 'Paris', 'Lens', 'Grenoble',

['Barcelone', 'Pampelune', 'Ibiza']]
\end{center}
\end{Exemple}

\subsectionnn{Différence}

Alors que la méthode \texttt{append} ajoute exactement ce que l'on veut (dans le deuxième exemple, on ajoute une liste et c'est bel et bien une liste qui est ajoutée comme item dans la liste \texttt{villes}), la méthode  \texttt{extend} \textit{étend} la liste (comme son nom l'indique d'ailleurs).

\Par


Mais les deux méthodes n'admettent qu'un seul argument.

Ainsi, \texttt{liste.append('bidule','truc')} est impossible; pour ajouter deux\linebreak items, il faut écrire deux instructions :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
liste.append('bidule')\\
liste.append('truc')
\end{tabularx}

\subsection{La liste des premiers entiers : la fonction range}

Il est très souvent nécessaire d'avoir une liste de la forme :
\begin{center}
\texttt{[0,1,2,3,4,5,...,100]}
\end{center}
Plutôt que de la rentrer au clavier (ce qui peut être très long si on va jusqu'à 1~million), le fonction \texttt{range} s'offre à nous.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
range(10)
\end{tabularx}

\Par

constitue la liste :
\begin{center}
\texttt{[0,1,2,3,4,5,6,7,8,9]}
\end{center}

\Par

Elle est constituée de 10 items, mais ne va pas jusqu'à 10.
\end{Exemple}

\begin{Remarque}
cette fonction est souvent utilisée dans les boucles. Par exemple, le programme : 

\begin{listing}{}{03-crs-01.py}\end{listing}

\Par

affiche \og 45 \fg{} car $0+1+2+3+4+5+6+7+8+9=45$.
\end{Remarque}

\subsection{\'Ecrire une matrice}

\begin{defin}
Une \textit{matrice} est un tableau contenant des nombres. Elle est souvent entourée de parenthèses ou de crochets.
\end{defin}

\begin{Exemple}
on considère le système linéaire suivant :
\[
\begin{cases}
2x-5y+3=0\\
7x+4y-1=0
\end{cases}
\]
On peut représenter ce système par un tableau :

\Par

\begin{center}
\begin{tabular}{|L|*3{Zc|}}
\tabulartitle\hline
Variables & $x$ & $y$ & constantes\\\hline
Ligne 1 & 2 & $-5$ & 3\\\hline
Ligne 2 & 7 & 4 & $-1$\\\hline
\end{tabular}
\end{center}

\Par

La matrice représentant ce système peut alors être :

\Par

\[
\begin{pmatrix}
2&-5&3\\
7&4&-1
\end{pmatrix}
\]
\end{Exemple}

Pour représenter une matrice en informatique, on utilise une liste dont tous les items sont des listes.

La matrice de l'exemple peut alors s'écrire :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
matrice = [[2,-5,3],[7,4,-1]]
\end{tabularx}

\Par

Chaque item est une liste contenant tous les coefficients d'une ligne.

\subsection{Construire une liste par compréhension}

\begin{defin}
\textit{Construire une liste par compréhension} signifie simplifier le code pour le rendre plus lisible et plus rapide.
On utilise alors la syntaxe suivante :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
ma\verb+_+liste = 
[<fonction sur item> for <item> in <liste> if <condition>]
\end{tabularx}
\end{defin}

Voyons sur un exemple ce que cela peut donner.

\begin{Exemple}
on considère la liste :

\Par

\begin{center}
\ttfamily
liste = [1,4,2,7,1,9,0,3,4,6,6,6,8,3]
\end{center}

\Par

On souhaite créer une autre liste à partir de celle-ci en ne gardant que les valeurs strictement supérieures à 5.

On peut bien entendu utiliser le code suivant :

\begin{listing}{}{03-crs-02.py}\end{listing}

\Par

Construire la liste par compréhension donne ceci :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
new\verb+_+list = [i for i in liste if i > 5]
\end{tabularx}

Dans cet exemple,
\begin{itemize}
\item \texttt{<fonction item>} est représenté par \texttt{i}. Autrement dit, la fonction utilisée est celle qui prend pour valeur celle de l'item;
\item \texttt{<condition>} est ici : \texttt{i > 5}. On ne prend que les valeurs qui satisfont cette condition.
\end{itemize}
\end{Exemple}

\enlargethispage*{\baselineskip}

\begin{solintro}
\begin{questions}
\item \texttt{a = [[-3,1,0],[1,-1,2],[0,-3,5]]}

\item La fonction \texttt{valabs(liste)} est :

\begin{listing}{}{03-crs-03.py}\end{listing}

\BreakWithoutItem

Explications :

\begin{itemize}
\item l'instruction \texttt{for i in range(len(liste))} fait en sorte que l'on prenne les entiers de 0 à \texttt{len(liste)-1};
\item dans cette boucle, l'instruction \texttt{liste[i]=abs(liste[i])} remplace l'item de rang \texttt{i} par sa valeur absolue, c'est-à-dire par la même valeur sans le signe \og $-$ \fg{}  quand il y en a un;
\item une fois la boucle terminée, une fois la liste parcourue, on retourne la valeur de la nouvelle liste ainsi obtenue.
\end{itemize}

\item \texttt{b = [valabs(i) for i in a]}

Cette instruction permet de construire une liste \texttt{b} contenant toutes les valeurs de la liste \texttt{a} sans leur signe.

\item La fonction suivante calcule la somme des coefficients d'une matrice :

\begin{listing}{}{03-crs-04.py}\end{listing}
\end{questions}
\end{solintro}

\enlargethispage*{4em}

\section{Les tuples (appelés aussi p-uplets)}

\begin{exointro}{\null}
Compléter le code suivant afin qu'il affiche les différentes valeurs que prend la variable \texttt{d}, différence (positive) entre les deux arguments du tuple \texttt{t}, tant que cette différence est inférieure ou égale à \numprint{40000}.

\begin{listing}{}{03-crs-05.py}\end{listing}
\end{exointro}

\subsection{Définition et affectation}

\begin{defin}
On appelle \textit{tuple} toute liste non modifiable. 
\end{defin}

On déclare un tuple comme une liste, si ce n'est que les crochets sont remplacés par des parenthèses.

\begin{Exemples}
\begin{itemize}
\item On peut imaginer que le code suivant définit un point $A$ de coordonnées $(1~;~-2)$ dans un repère cartésien.

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
point1 = ('A',1,-2)
\end{tabularx}

\item On peut aussi définir un tuple vide :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
t = tuple()
\end{tabularx}

\item On peut aussi définir un tuple à partir d'une chaîne de caractères :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
t1, t2 = tuple('python'), tuple('maths')
\end{tabularx}

\Par

Dans ce cas, :
\begin{center}
\texttt{t1 = ('p','y','t','h','o','n')}  et  \texttt{t2 = ('m','a','t','h','s')}.
\end{center}
\end{itemize}
\end{Exemples}

\subsection{Ajouter un argument à un tuple}

On ne peut pas ajouter un argument entre le 1\ier{} et le dernier argument d'un tuple. On ne peut le faire qu'au début.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
t = tuple('bcd')\\
t = ('a',)+t[1:]
\end{tabularx}
\end{Exemple}


\subsection{Pourquoi utiliser un tuple ?}

Il est très souvent question de tuples comme résultat d'une fonction.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
q,r = divmod(7,3)
\end{tabularx}

\Par

La fonction \texttt{divmod} renvoie un tuple (plus précisément, un couple) dont le premier argument est le quotient de la division euclidienne de 7 par 3, et le second, son reste.
\end{Exemple}

\subsection{Disperser un tuple}

Disperser un tuple, c'est le \og casser \fg{} en plusieurs variables (autant que d'arguments du tuple).

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
t = divmod(56,15)\\
print(*t)
\end{tabularx}

\Par

Ce code nous renvoie les deux nombres du tuple (à savoir ici 3 et 11).
\end{Exemple}

\begin{solintro}
\begin{listing}{}{03-solintro-02.py}\nathanliveProgWithoutText
\end{listing}

\Par

Pour calculer la différence (positive) entre deux nombres, on utilise la fonction native \texttt{abs} (valeur absolue) car on ne sait pas à l'avance si le premier argument du tuple est plus grand ou plus petit que le second.

De plus, la fonction \texttt{f(x,y)} admet deux arguments, et non un tuple, donc il est nécessaire de disperser le tuple dans la boucle \texttt{while} (\texttt{t = f(*t)}).
\end{solintro}


\section{Les dictionnaires}

\subsection{Définition}

\begin{defins}
Un \textit{dictionnaire} est une sorte de liste si ce n'est qu'à la place des index (des nombres), on utilise des \textit{clés} (c'est-à-dire des valeurs autres que des nombres).
\end{defins}

\newpage

Pour définir un dictionnaire, on procède de la même manière que pour les listes, en remplaçant les crochets par des accolades \og \{ \fg{} et \og \} \fg.


\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X@{}}
infos = \{'nom':'Dupont' , 'prenom':'Gilbert' , 'age':'54'\}
\end{tabularx}
\end{Exemple}

On peut aussi utiliser des tuples comme clés.


\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
p = \{ \}\\
p[(-1,1)] = 'A'\\
p[(2,5)] = 'B'\\
print(p)
\end{tabularx}

\Par

Ce code affiche :
\begin{center}
\texttt{\{(-1, 1): 'A', (2, 5): 'B'\}}
\end{center}
\end{Exemple}

\subsection{Opérations sur les dictionnaires}

\subsubsection{Récupérer une valeur}

La méthode \texttt{get} permet de récupérer une valeur connaissant sa clé.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
infos = \{\\\hspace*{1cm}'nom':'Dupont' ,\\\hspace*{1cm}'prenom':'Gilbert' ,\\\hspace*{1cm}'age':'54'\\\hspace*{1cm}\}\\
infos.get('prenom')
\end{tabularx}

\Par

Ce programme affiche : \og \texttt{Gilbert} \fg.
\end{Exemple}

Si la clé n'est pas trouvée, rien ne s'affiche. Si vous le souhaitez, vous pouvez afficher un message par défaut quand la clé n'est pas trouvée.

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
infos = \{\\\hspace*{1cm}'nom':'Dupont' ,\\\hspace*{1cm}'prenom':'Gilbert' ,\\\hspace*{1cm}'age':'54'\\\hspace*{1cm}\}\\
infos.get('adresse','clé introuvable')
\end{tabularx}
\end{Exemple}

\newpage

\subsubsection{Vérifier l'existence d'une clé}

Le mot-clé \texttt{in} renvoie un booléen dont la valeur est \og True \fg{} si la clé est présente.

\begin{Exemple}
\begin{listing}{}{03-crs-07.py}\end{listing}
\end{Exemple}

\begin{attention}
Sur certains sites Internet, il est indiqué que pour vérifier l'existence d'une clé, on peut utiliser la méthode \texttt{has\_key}. Ceci n'est plus valable depuis la version 3 de Python.
\end{attention}

\subsubsection{Récupérer les clés et valeurs par une boucle}

Quand un dictionnaire est très long, on peut utiliser une boucle pour récupérer toutes les clés et valeurs. Ceci est possible à l'aide de la méthode \texttt{items}.

\begin{Exemple}
\begin{listing}{}{03-crs-08.py}\end{listing}
\end{Exemple}

\subsection{Recherches avec conditions}

Imaginons un tableau où chaque ligne représente un individu. 

Dans chaque colonne, nous enregistrons des informations sur cet individu.

Il est très souvent utile d'afficher ou de sélectionner uniquement quelques lignes en fonction de ce que l'on recherche.

\begin{Exemple}
le programme suivant créé un tableau réunissant quelques informations sur les clients d'un magasin.
\end{Exemple}

\begin{listing}{}{03-crs-16.py}\end{listing}

\Par

Nous avons créé un tableau où chaque ligne est un dictionnaire (pour plus de lisibilité et de compréhension).

\begin{itemize}
\item Nous souhaitons dans un premier temps afficher tous les clients dont l'âge est inférieur à 50 ans. On peut alors utiliser le programme suivant :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
for i in range(len(clients)):\\
\hspace*{1cm}   if int(clients[i]['age'])<50:\\
\hspace*{2cm}      print(clients[i])
\end{tabularx}

\Par

On obtient :

\begin{center}
\ttfamily
\{'nom':'Dupont','prenom':'Pierre','age':'34','genre':'m'\}

\{'nom':'Sylla','prenom':'Anne','age':'48','genre':'f'\}
\end{center}

\item Nous souhaitons à présent afficher les clients de genre \og m \fg{} (pour \og masculin \fg)  :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
for i in range(len(clients)):\\
\hspace*{1cm}   if clients[i]['genre'] == 'm':\\
\hspace*{2cm}      clients[i]
\end{tabularx}

\Par

On obtient :

\begin{center}
\ttfamily
\{'nom':'Gilbert','prenom':'Jean','age':'54','genre':'m'\}

\{'nom':'Dupont','prenom':'Pierre','age':'34','genre':'m'\}
\end{center}
\end{itemize}

La première ligne \og \texttt{for i in range(len(clients)):} \fg{} parcourt toutes les lignes du tableau \texttt{clients} (ici, \texttt{len(clients))} est égal à 3 car il y a 3 lignes, 3~clients).

\Par

Ensuite, on insère notre condition et l'instruction à exécuter en cas de succès. À noter que pour le premier algorithme, il a fallu convertir \texttt{clients[i]['age']} en entier afin de pouvoir tester sa valeur.

\subsubsection{Copier un dictionnaire}

Comme nous l'avons vu précédemment pour les listes, écrire \og \texttt{dic2 = dic1} \fg{} ne fait que créer une copie dépendante de l'original. Il est préférable de passer par la méthode \texttt{copy}.

\vspace*{-0.4em}
\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
infos = \{'nom':'Dupont' , 'prenom':'Gilbert' , 'email':'gilbert@dupont.fr' \}\\
backup = infos.copy()
\end{tabularx}

\Par

Ainsi, on peut modifier le dictionnaire \texttt{infos} tout en ne changeant pas le dictionnaire \texttt{backup}.
\end{Exemple}

\subsubsection{Supprimer une clé et sa valeur}

On supprime une clé et sa valeur avec la fonction \texttt{del}.

\vspace*{-0.4em}
\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
infos = \{'nom':'Dupont' , 'prenom':'Gilbert' , 'email':'gilbert@dupont.fr' \}\\
del infos['email']\\
print(infos)
\end{tabularx}

\Par

Le programme affiche :
\begin{center}
\texttt{\{'nom': 'dupont', 'prenom': 'Gilbert'\}}
\end{center}
\end{Exemple}

\section{Traitement de données en table}
\enlargethispage*{4em}

\begin{exointro}{\null}
Sur un site Internet, Eugénie a téléchargé une feuille de calcul dans laquelle sont respectivement enregistrés par colonne les noms, prénoms, adresses, codes postaux, villes, départements, numéro de téléphone et courriel des membres de son association. Elle sauvegarde ces données dans le fichier CSV nommé \textit{feuille.csv}. \'Ecrire un programme Python qui lui permet :

\begin{questions}
\item d'importer les données de son fichier CSV dans une table nommée \texttt{data};
\item de rechercher les doublons et de ne garder que les entrées uniques dans une table nommée \texttt{membres};
\item de trier les données dans l'ordre alphabétique suivant les noms et d'afficher toutes les valeurs de la table;
\item de trier les données dans l'ordre alphabétique suivant les départements et d'afficher toutes les valeurs de la table;
\item et n'afficher que les données des membres habitant la ville de Toulouse.
\end{questions}
\vspace*{-1.2em}
\end{exointro}

\newpage

\subsection{Création d'une table}

\subsubsection{Définition}

\begin{defin}
On peut définir une table comme étant une liste où les items sont des listes, des tuples ou des dictionnaires.
\end{defin}

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
tableau = [ [1,2,3] , [4,5,6] ]
\end{tabularx}

\Par

Nous avons ici construit le tableau suivant :

\Par

\begin{center}
\begin{tabular}{|Zc|Zc|Zc|}
\hline
1&2&3\\
\hline
4&5&6\\
\hline
\end{tabular}
\end{center} 
\end{Exemple}

\begin{Remarque}
nous avons déjà rencontré des tables dans le chapitre précédent quand nous avons parlé de matrices.
\end{Remarque}

\subsubsection{Table à nombre de lignes et colonnes variable}

Pour construire un tableau dont les dimensions sont entrées au clavier, on pourra procéder ainsi :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
lignes = int(input("Nombre de lignes : "))\\
colonnes = int(input("Nombre de colonnes : "))\\
tableau = [[0] * colonnes for i in range(lignes)]
\end{tabularx}

\Par

Ici, on construit un tableau rempli de \og 0 \fg.

\subsubsection{À partir d'un fichier CSV}

\begin{defin}
Un fichier CSV (\textit{Coma Separated Values}) est un fichier texte contenant plusieurs données séparées par une virgule.
\end{defin}

\begin{Exemple}
le fichier \texttt{contact.csv} suivant est un fichier CSV :

\Par

\ttfamily
Prénom,Nom,courriel,Âge,Ville

Robert,Lepingre,bobby@exemple.com,41,Paris

Jeanne,Ducoux,jeanne@exemple.com,32,Marseille

Pierre,Lenfant,pierre@exemple.com,23,Rennes
\end{Exemple}

Pour importer les données d'un fichier CSV et les mettre dans une table, on utilise le module \texttt{csv} de Python.

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
import csv\\
with open('contacts.csv', newline='') as csvfile:\\
\hspace*{1cm}data = list(csv.reader(csvfile))
\end{tabularx}

\Par

On construit ici une table \texttt{data} où chaque item est une liste contenant les informations du fichier CSV séparées par une virgule.

\subsection{Recherche dans une table}

Pour cette section, nous allons nous appuyer sur l'exemple suivant :

\begin{Exemple}
on souhaite construire la table d'addition des nombres de 1 à 9. Pour cela, on utilise le programme suivant :

\begin{listing}{}{03-crs-09.py}\end{listing}

\begin{itemize}
\item La 1\iere{} ligne construit une table remplie de \og 0 \fg{} , de dimension $9 \times 9$.
\item La ligne \og \texttt{for c in range(9):} \fg{} créé une boucle pour \texttt{c} allant de 0 à 9\linebreak (\texttt{c} représentant ici le nombre de colonnes souhaitées).
\item La ligne \og \texttt{for l in range(9):} \fg{} créé une boucle pour \texttt{l} allant de 0 à 9\linebreak (\texttt{l} représentant ici le nombre de lignes souhaitées).
\item \og \texttt{add[c][l]} \fg{} représente la somme de \texttt{c} et \texttt{l}, mais comme il y a un décalage au niveau des variables de boucles, on doit leur ajouter 1 à chacune, d'où le \og \texttt{l+c+2} \fg).
\end{itemize}
\end{Exemple}

\subsubsection{Rechercher la présence d'une valeur dans une table}

Nous souhaitons savoir si le nombre \og 10 \fg{} apparaît dans le tableau \texttt{add} créé dans l'exemple précédent.

Pour cela, nous allons le parcourir à l'aide d'une boucle.

\begin{listing}{}{03-crs-10.py}\end{listing}

\Par

\begin{itemize}
\item On commence par déclarer un booléen \texttt{test} qui, par défaut, vaut \textit{False}. Il nous servira à signifier la présence du \og 10 \fg{} dans le tableau.
\item \og \texttt{for valeur in add:} \fg{} signifie que l'on parcourt le tableau \texttt{add} et que chaque ligne est représentée par la variable \texttt{valeur}.
\item \og \texttt{if 10 in valeur} \fg{} signifie que l'on teste si \og 10 \fg{} figure dans la variable \texttt{valeur}; si tel est le cas, on change la valeur du booléen \texttt{test} en \textit{True} et on arrête la boucle (avec \texttt{break}).
\item On termine en affichant le booléen \texttt{test}.
\end{itemize}

\begin{Remarque}
la présence de \texttt{break} n'est pas réellement utile pour un tableau aussi petit que le nôtre, mais pour un tableau plus volumineux, il est fortement conseillé de l'utiliser afin de ne pas continuer la boucle pour rien.
\end{Remarque}

\subsubsection{Afficher toutes les instances d'une valeur}
\label{afficher-instance}

Maintenant, nous souhaitons afficher toutes les valeurs \og 10 \fg{} qui sont contenues dans notre tableau \texttt{add}. Pour cela, nous allons légèrement modifier le programme précédent.

\begin{listing}{}{03-crs-11.py}\end{listing}

\Par

Le programme renvoie alors :

\begin{center}
\ttfamily
10 est dans add[0][8]

10 est dans add[1][7]

10 est dans add[2][6]

10 est dans add[3][5]

10 est dans add[4][4]

10 est dans add[5][3]

10 est dans add[6][2]

10 est dans add[7][1]

10 est dans add[8][0]
\end{center}

Expliquons les instructions de ce programme :

\begin{itemize}
\item \og \texttt{for valeur in add:} \fg{} est la boucle qui nous permet de parcourir le tableau \texttt{add}, et chaque item sera alors désigné par \texttt{valeur}. Mais attention : comme il s'agit d'un tableau, cet item est une liste.

\item \og \texttt{if 10 in valeur} \fg{} a pour but de vérifier si \og 10 \fg{} est dans la liste \texttt{valeur}. Si tel est le cas, on exécute l'instruction suivante.

\item \og \texttt{add.index(valeur)} \fg{} désigne l'index (ici, le numéro de ligne du tableau en quelque sorte) de l'item (la liste \og ligne \fg) où a été trouvé \og 10 \fg. 

\newpage

Donc en tapant \og \texttt{str(add.index(valeur))} \fg, on convertit ce numéro en chaîne de caractères pour l'afficher à l'aide de \texttt{print}.

Quant à \og \texttt{valeur.index(10)} \fg, cela représente l'index du nombre \og 10 \fg{} dans la liste \texttt{valeur}. On a ensuite converti en chaîne de caractères, comme précédemment.
\end{itemize}

Si l'aspect de la sortie de ce programme ne convient pas, si l'on souhaite afficher directement la somme qui donne \og 10 \fg, on pourra utiliser le programme suivant :

\begin{listing}{}{03-crs-12.py}\end{listing}

\Par

La sortie est alors :

\begin{multicols}{2}
\begin{center}
\ttfamily
10 = 1 + 9

10 = 2 + 8

10 = 3 + 7

10 = 4 + 6

10 = 5 + 5

10 = 6 + 4

10 = 7 + 3

10 = 8 + 2

10 = 9 + 1
\end{center}
\end{multicols}


\subsubsection{Recherche de doublons dans une table}

Reprenons l'exemple précédent, où la table \texttt{infos} admet pour items des dictionnaires.

Pour chasser les doublons, c'est-à-dire les dictionnaires identiques, on peut procéder ainsi :

\begin{listing}{}{03-crs-13.py}\end{listing}

\newpage

Explications:
\begin{itemize}
\item on crée d'abord une table vide \texttt{data} dans laquelle nous avons l'intention de mettre tous les dictionnaires différents;
\item on parcourt ensuite la table \texttt{infos};
\item on initialise un booléen \texttt{p} (pour \og présence \fg) à \textit{False} pour signifier que l'item de \texttt{infos} sur lequel on est n'est, par défaut, pas présent dans la table \texttt{data};
\item on parcourt ensuite \texttt{data} dans le but de voir si \texttt{i} y est. Si tel est le cas (\texttt{if j==i}, c'est-à-dire si l'item de \texttt{data} coïncide avec celui de \texttt{infos} sur lequel on est) alors le booléen passe à \textit{True};
\item une fois \texttt{data} parcourue, on regarde si le booléen \texttt{p} est toujours à \textit{False}. Si tel est le cas, c'est que nous n'avons pas rencontré d'items de \texttt{data} qui soit identique à l'item de \texttt{infos} sur lequel on se trouve. Dans ce cas, on ajoute cet item à \texttt{data}.
\end{itemize}

On ajoute ainsi chaque item de \texttt{infos} tant que celui-ci ne coïncide pas avec un item déjà présent dans \texttt{data}.

Au final, \texttt{data} sera constitué d'items tous différents.

\subsection{Tri sur une colonne}

\subsubsection{Tri suivant la première colonne d'une table}

Nous allons partir de la table \texttt{data} suivante :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
data = [\\
\hspace*{1cm}    ("Clément", 14, 16),\\
\hspace*{1cm}    ("Charles", 12, 15),\\
\hspace*{1cm}    ("Ariane", 14, 18),\\
\hspace*{1cm}    ("Thomas", 11, 12),\\
\hspace*{1cm}    ("Damien", 12, 15),\\
]
\end{tabularx}

Pour trier les items suivant la première colonne, on utilisera la fonction \texttt{sorted} si on ne souhaite pas modifier la table. Le code :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
print(sorted(data))
\end{tabularx}

\Par

renvoie :\enlargethispage*{\baselineskip}

\begin{center}
\ttfamily 
[\\
	('Ariane', 14, 18),\\
    ('Charles', 12, 15),\\
    ('Clément', 14, 16),\\
    ('Damien', 12, 15),\\
    ('Thomas', 11, 12)\\
]
\end{center}

sans affecter la table initiale.

Si on souhaite modifier l'ordre non plus à l'affichage mais dans la table elle-même, on utilisera la méthode \texttt{sort()}:

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
data.sort()
\end{tabularx}

\subsubsection{Trier suivant une colonne quelconque}

\subsubsectionnn{Les fonctions \og lambda \fg}

Imaginons que nous souhaitions créer simplement une fonction qui calcule le carré d'un nombre.

On peut bien sûr écrire :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
def carre(x):\\
\hspace*{1cm}	return x**2
\end{tabularx}

\Par

Mais on peut aussi faire appel au mot-clé \texttt{lambda} :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
carre = lambda x : x**2
\end{tabularx} 

\Par

On dit ici que la fonction définie, la fonction \texttt{carre}, est une fonction \textit{lambda}.

\Par

La syntaxe d'une fonction lambda est la suivante :

\begin{itemize}
\item on commence par lui donner un nom, et on fait suivre le signe \og = \fg;
\item ensuite, on écrit le mot-clé \og lambda \fg{} suivi de la variable. S'il y a plusieurs\linebreak variables, on les sépare par une virgule;
\item ensuite, on écrit \og : \fg{} suivi de l'instruction à exécuter.
\end{itemize}

\begin{Exemple}~\par 
\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
somme = lambda x,y : x+y
\end{tabularx}

\Par

La fonction \texttt{somme} calcule ici la somme des deux arguments. Ainsi, \texttt{somme(3,5)} renvoie le nombre \og 8 \fg.
\end{Exemple}

\subsubsectionnn{Le tri}

\texttt{sorted} et \texttt{sort()} admettent un paramètre optionnel appelé \texttt{key}. C'est grâce à cet argument que l'on va pouvoir sélectionner la colonne sur laquelle on va effectuer le tri, et ce à l'aide d'une fonction lambda.

\Par

Reprenons l'exemple précédent de la table \texttt{data}. Pour trier suivant la colonne 2, on va écrire :

\Par

\begin{tabularx}{\linewidth}{@{\hspace*{5mm}}>{\ttfamily}X}
data.sort(key = lambda colonnes: colonnes[1])
\end{tabularx}

\begin{attention}
N'oubliez pas que la 1\iere{} colonne est désignée par  \texttt{colonne[0]}, et donc la colonne 2 est \texttt{colonne[1]}.
\end{attention}

\begin{Remarque}le mot \og colonne \fg{} peut être remplacé par tout autre mot, comme par exemple : \texttt{data.sort(key=lambda col: col[1])}.\end{Remarque}

\subsection{Fusion de deux tables}

La fusion de deux tables a déjà été traitée précédemment : elle est possible à l'aide de la fonction \texttt{extend}.

\begin{Exemple}
\begin{listing}{}{03-crs-14.py}\end{listing}

\Par

Ici, nous avons pris deux fichiers CSV, nous les avons converti en deux tables, puis nous les avons fusionné: la table \texttt{data} contient au final toutes les données.
\end{Exemple}

\enlargethispage*{4em}

\begin{solintro}
\begin{listing}{}{03-solintro-03.py}\nathanliveProgWithoutText
\end{listing}\par~ 
\end{solintro}
