Des enseignants et leurs cours
On utilise dans cet exercice la table personnes.csv et la table cours.csv à télécharger ci-dessous :
Contenu du fichier :
id_personne | nom | prenom | anneeNaissance |
1 | Labrosse | Adam | 2000 |
2 | Gemlamorte | Adèle | 1985 |
3 | Auboisdormant | Abel | 2001 |
4 | Etpan | Ahmed | 1975 |
5 | Térieur | Alain | 1999 |
6 | Térieur | Alex | 1976 |
7 | Proviste | Alain | 2000 |
8 | Verse | Alain | 1970 |
9 | Ception | Alex | 2001 |
10 | Ainé | Ali | 1975 |
11 | Gator | Ali | 2001 |
12 | Bistraux | Alonzo | 2001 |
13 | Patamob | Alphonse | 1970 |
14 | Ficulté | Andy | 1980 |
15 | Rectdustade | Andy | 2000 |
16 | Verserre | Annie | 2001 |
17 | Boréal | Aurore | 1985 |
18 | Nor | Paul | 1985 |
19 | Dejeu | Bernadette | 2001 |
20 | Dajeun | Bruno | 1984 |
21 | Hiple | Candice | 2000 |
La colonne id_enseignant fait référence à la colonne id_personne de la table personnes.
Ainsi on sait, par exemple, que le cours sur la théorie des graphes est assuré par Adèle Gemlamorte.
Contenu du fichier cours.csv :
id_cours | id_enseignant | intitule |
1 | 2 | théorie des graphes |
2 | 4 | programmation objet |
3 | 6 | programmation fonctionnelle |
4 | 8 | théorie des automates |
5 | 10 | base de données relationnelle |
6 | 13 | réseaux |
7 | 14 | langage python |
8 | 17 | html et css |
9 | 18 | javascript |
10 | 20 | java |
11 | 2 | algorithmique |
12 | 4 | tests logiciels |
13 | 6 | intelligence artificielle |
14 | 8 | UML |
15 | 10 | XML |
16 | 13 | scheme |
17 | 14 | merise |
18 | 14 | webgl |
19 | Unix |
Question
Vous devez créer une liste de dictionnaires. Les clefs de chaque dictionnaire seront 'id_personne', 'nom', 'prenom', 'id_cours', 'intitule'. Cette liste met donc en face de chaque personne les cours qu'elle assure.
Chaque personne devra apparaître dans la liste même si elle n'assure pas de cours ('id_cours' et 'intitule' seront dans ce cas associées à ''
).
Une personne assurant plusieurs cours apparaît sur autant de lignes...
Un cours qui n'est assuré par personne devra aussi apparaître (avec ''
pour valeur associée aux clefs identifiant l'enseignant).
La liste devra être triée suivant le nom des personnes (ordre croissant). Et pour une même personne, les lignes seront triées suivant le nom des cours (ordre croissant).
La liste créée sera envoyée dans un fichier csv.
Indice
Un relecture de la page précédente vous permettra à coût sûr de réussir !
Indice
Lors d'un premier parcours, on associe enseignant et cours ; lors d'une seconde boucle, on ajoute les personnes ne donnant pas de cours...
Enfin, on ajoute les cours n'ayant pas d'enseignant.
Solution
import csv
def de_csv_vers_dico(fichier):
"""
fichier -- nom d'un fichier csv (sans l'extension)
renvoie la liste de dictionnaires associée au fichier.
"""
with open(fichier + '.csv', newline='') as fichiercsv:
lecture = csv.DictReader(fichiercsv, delimiter=',')
return [ligne for ligne in lecture]
def de_dico_vers_csv(liste, nomFichier):
"""
liste -- liste de dictionnaires
nomFichier -- nom du fichier créé (sans extension)
crée le fichier csv contenant les contenus des dictionnaires
"""
with open(nomFichier + '.csv', 'w', newline='') as fichiercsv:
entete = [clef for clef in liste[0].keys()]
ecriture = csv.DictWriter(fichiercsv, fieldnames=entete)
ecriture.writeheader()
for ligne in liste:
ecriture.writerow(ligne)
personnes = de_csv_vers_dico('personnes')
cours = de_csv_vers_dico('cours')
# premier parcours, on associe enseignant et cours
liste = []
for discipline in cours:
for personne in personnes:
if discipline['id_enseignant'] == personne['id_personne']:
dico = {'id_personne': personne['id_personne'],
'nom': personne['nom'],
'prenom': personne['prenom'],
'id_cours': discipline['id_cours'],
'intitule': discipline['intitule']
}
liste.append(dico)
# seconde boucle, on ajoute les personnes ne donnant pas de cours
for personne in personnes:
present = False
for dico2 in liste:
if personne['id_personne'] == dico2['id_personne']:
present = True
if not present:
liste.append({'id_personne': personne['id_personne'],
'nom': personne['nom'],
'prenom': personne['prenom'],
'id_cours': '',
'intitule': ''}
)
# troisième boucle, on ajoute les cours n'ayant pas d'enseignant
for crs in cours:
present = False
for dico3 in liste:
if crs['id_cours'] == dico3['id_cours']:
present = True
if not present:
liste.append({'id_personne': '',
'nom': '',
'prenom': '',
'id_cours': crs['id_cours'],
'intitule': crs['intitule']}
)
# on trie:
liste.sort(key= lambda x:x['intitule'])
liste.sort(key= lambda x:x['nom'])
de_dico_vers_csv(liste, 'enseignements')
Remarque :
L'ordre des lettres est l'ordre ASCII, les majuscules sont situées avant les minuscules, ce qui explique que par exemple pour Ali Ainé, le cours XML soit placé avant le cours 'base de données relationnelle'.
Pour régler ce problème, il suffit de trier suivant les chaînes préalablement toutes passées en minuscule, ce qui se fait facilement avec la méthode lower en remplaçant les deux lignes de tris par:
liste.sort(key= lambda x:x['intitule'].lower())
liste.sort(key= lambda x:x['nom'].lower())