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

1
import csv
2
3
def de_csv_vers_dico(fichier):
4
    """
5
    fichier -- nom d'un fichier csv (sans l'extension) 
6
7
    renvoie la liste de dictionnaires associée au fichier.
8
    """
9
    with open(fichier + '.csv', newline='') as fichiercsv:
10
        lecture = csv.DictReader(fichiercsv, delimiter=',')
11
        return [ligne for ligne in lecture]
12
13
def de_dico_vers_csv(liste, nomFichier):
14
    """
15
    liste -- liste de dictionnaires
16
    nomFichier -- nom du fichier créé (sans extension)
17
18
    crée le fichier csv contenant les contenus des dictionnaires 
19
    """
20
    with open(nomFichier + '.csv', 'w', newline='') as fichiercsv:
21
        entete = [clef for clef in liste[0].keys()]
22
        ecriture = csv.DictWriter(fichiercsv, fieldnames=entete)
23
        ecriture.writeheader()
24
        for ligne in liste:
25
            ecriture.writerow(ligne)
26
27
personnes = de_csv_vers_dico('personnes')
28
cours = de_csv_vers_dico('cours')
29
30
# premier parcours, on associe enseignant et cours
31
liste = []
32
for discipline in cours:
33
    for personne in personnes:
34
        if discipline['id_enseignant'] == personne['id_personne']:
35
            dico = {'id_personne': personne['id_personne'],
36
                    'nom': personne['nom'],
37
                    'prenom': personne['prenom'],
38
                    'id_cours': discipline['id_cours'],
39
                    'intitule': discipline['intitule']
40
            }
41
            liste.append(dico)
42
43
# seconde boucle, on ajoute les personnes ne donnant pas de cours
44
for personne in personnes:
45
    present = False
46
    for dico2 in liste:
47
        if personne['id_personne'] == dico2['id_personne']:
48
            present = True
49
    if not present:
50
        liste.append({'id_personne': personne['id_personne'],
51
                    'nom': personne['nom'],
52
                    'prenom': personne['prenom'],
53
                    'id_cours': '',
54
                    'intitule': ''}
55
                    )
56
57
# troisième boucle, on ajoute les cours n'ayant pas d'enseignant
58
for crs in cours:
59
    present = False
60
    for dico3 in liste:
61
        if crs['id_cours'] == dico3['id_cours']:
62
            present = True
63
    if not present:
64
        liste.append({'id_personne': '',
65
                    'nom': '',
66
                    'prenom': '',
67
                    'id_cours': crs['id_cours'],
68
                    'intitule': crs['intitule']}
69
                    )
70
71
# on trie:
72
liste.sort(key= lambda x:x['intitule'])
73
liste.sort(key= lambda x:x['nom'])
74
75
76
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:

1
liste.sort(key= lambda x:x['intitule'].lower())
2
liste.sort(key= lambda x:x['nom'].lower())