Résultat :
Correction - Données en table
1. Manipulation de fichiers CSV
- On peut représenter un enregistrement par un dictionnaire.
- Une virgule (CSV : Comma Separated Values - Valeurs séparées par une virgule). Néanmoins, le format CSV autorise d'autres séparateurs.
- La table étant une liste de dictionnaires, on obtient donc le premier élément de la liste, c'est à dire un dictionnaire, donc une ligne de la table.
2. Opérations sur les tables
- Pour sélectionner des colonnes selon un critère donné, on va utiliser la fonction projection.
def projection(table, liste_attributs):
return [{clé:ligne[clé] for clé in ligne if clé in liste_attributs} for ligne in table]
- La fonction select ici va sélectionner les lignes dont une des valeurs vaut 19. On obtient donc :
[{'Prénom': 'Chandler', 'Math': '19', 'Anglais': '15', 'NSI': '17'},
{'Prénom': 'Ross', 'Math': '14', 'Anglais': '19', 'NSI': '13'}]
- Il y a deux (2) noms qui sont communs aux tables : on aura donc deux (2) lignes. De plus, la table U rajoute ses deux (2) colonnes (Âge, Mail) aux quatre de la table T : on aura donc 6 (six) colonnes.
3. Déterminer des fonctions basiques
- Puisqu'il s'agit de compter le nombre de lignes, donc d'enregistrements, on peut donc utiliser la fonction len pour obtenir la longueur de la liste de dictionnaires.
- La liste des attributs d'une table correspond aux clés du premier dictionnaire (en supposant que la table est cohérente) :
4. Reconnaître une fonction
def mystère(t, cs):
t_p = []
for l in t :
nvlle_l = {}
for c in l:
if c in cs:
nvelle_l[c] = l[c]
t_p.append(nvlle_l)
return t_p
Cette fonction réalise une projection : elle crée une nouvelle table ne contenant que les colonnes (attributs) spécifiés dans la liste cs.
test la table d'origine (liste de dictionnaires)csest la liste des colonnes à conserver- Pour chaque ligne
lde la table, on crée un nouveau dictionnairenvlle_lne contenant que les clés présentes danscs - On retourne la nouvelle table
t_p
Remarque : Il y a une erreur dans le code original (nvelle_l au lieu de nvlle_l). La version corrigée serait :
def projection(table, colonnes):
table_projetee = []
for ligne in table:
nouvelle_ligne = {}
for colonne in ligne:
if colonne in colonnes:
nouvelle_ligne[colonne] = ligne[colonne]
table_projetee.append(nouvelle_ligne)
return table_projetee
5. Tester la cohérence d'une table
- Fonction
coherencequi teste si chaque ligne a le même ensemble d'attributs :
def coherence(table):
"""
Teste si chaque ligne de la table a le même ensemble d'attributs
:param table: (list) une liste de dictionnaires
:return: (bool) True si la table est cohérente, False sinon
"""
if len(table) == 0:
return True
attributs_reference = set(table[0].keys())
for ligne in table:
if set(ligne.keys()) != attributs_reference:
return False
return True
- Fonction
doublonsqui vérifie si un attribut apparaît deux fois avec la même valeur :
def doublons(table, attribut):
"""
Vérifie si un attribut apparaît deux fois avec la même valeur
:param table: (list) une liste de dictionnaires
:param attribut: (str) le nom de l'attribut à vérifier
:return: (bool) True s'il y a des doublons, False sinon
"""
valeurs_vues = []
for ligne in table:
valeur = ligne[attribut]
if valeur in valeurs_vues:
return True
valeurs_vues.append(valeur)
return False
6. Lier tableur, fichier CSV et liste de dictionnaires
PlanningTwitch = [
{'NomStream': 'AntoineDaniel', 'Genre': 'M', 'Jeu': 'Fall_Guys', 'Numéro': '1'},
{'NomStream': 'MV', 'Genre': 'M', 'Jeu': 'Isaac', 'Numéro': '2'},
{'NomStream': 'AngleDroit', 'Genre': 'F', 'Jeu': 'Fall_Guys', 'Numéro': '3'},
{'NomStream': 'BagheraJones', 'Genre': 'F', 'Jeu': 'Fall_Guys', 'Numéro': '4'}
]
-
La première ligne de la feuille de calcul contient les en-têtes (attributs) :
NomStream | Genre | Jeu | Numéro -
Pour obtenir le fichier CSV correspondant :
-
La deuxième ligne du fichier CSV :
AntoineDaniel;M;Fall_Guys;1 -
La cellule C8 de la feuille correspondante : la table n'a que 5 lignes (1 en-tête + 4 données), donc C8 est vide.
-
Pour obtenir la valeur d'une cellule (par exemple C2, le jeu d'AntoineDaniel) :
-
Pour modifier le jeu de MV :
7. Ajouter une ligne ou une colonne
-
Pour obtenir la liste de dictionnaires depuis le fichier CSV :
-
Pour ajouter Rachel :
-
Fonction pour ajouter une colonne moyenne :
from copy import deepcopy
def ajouter_moyenne(table):
"""
Ajoute une colonne 'Moyenne' à chaque ligne de la table
:param table: (list) une liste de dictionnaires avec des notes
:return: (list) une nouvelle table avec la colonne Moyenne
"""
nouvelle_table = deepcopy(table)
for ligne in nouvelle_table:
math = int(ligne['Math'])
anglais = int(ligne['Anglais'])
nsi = int(ligne['NSI'])
moyenne = (math + anglais + nsi) / 3
ligne['Moyenne'] = '{:.1f}'.format(moyenne)
return nouvelle_table
- Pour ajouter une ligne contenant les moyennes par matière :
from copy import deepcopy
def ajouter_ligne_moyennes(table):
"""
Ajoute une ligne contenant les moyennes par matière
:param table: (list) une liste de dictionnaires avec des notes
:return: (list) une nouvelle table avec la ligne des moyennes
"""
nouvelle_table = deepcopy(table)
nb_eleves = len(nouvelle_table)
total_math = 0
total_anglais = 0
total_nsi = 0
for ligne in nouvelle_table:
total_math = total_math + int(ligne['Math'])
total_anglais = total_anglais + int(ligne['Anglais'])
total_nsi = total_nsi + int(ligne['NSI'])
ligne_moyennes = {
'Prénom': 'Moyenne',
'Math': '{:.1f}'.format(total_math / nb_eleves),
'Anglais': '{:.1f}'.format(total_anglais / nb_eleves),
'NSI': '{:.1f}'.format(total_nsi / nb_eleves)
}
nouvelle_table.append(ligne_moyennes)
return nouvelle_table
8. Sélectionner, trier, joindre
On définit les tables :
Hero = [
{'NumHero': '0', 'NomHero': 'Sangoku', 'VilleHero': 'Kyoto'},
{'NumHero': '1', 'NomHero': 'Naruto', 'VilleHero': 'Konoha'},
{'NumHero': '2', 'NomHero': 'Luffy', 'VilleHero': 'Fuchsia'},
{'NumHero': '3', 'NomHero': 'Ryo Saeba', 'VilleHero': 'Tokyo'},
{'NumHero': '4', 'NomHero': 'Saitama', 'VilleHero': 'Ville Z'},
{'NumHero': '5', 'NomHero': 'Onizuka', 'VilleHero': 'Tokyo'}
]
Armes = [
{'NumHero': '0', 'NomHero': 'Sangoku', 'Arme': 'Ki'},
{'NumHero': '1', 'NomHero': 'Naruto', 'Arme': 'Chakra'},
{'NumHero': '2', 'NomHero': 'Luffy', 'Arme': 'Corps'},
{'NumHero': '3', 'NomHero': 'Ryo Saeba', 'Arme': 'Magnum'},
{'NumHero': '4', 'NomHero': 'Saitama', 'Arme': 'Poing'},
{'NumHero': '5', 'NomHero': 'Onizuka', 'Arme': 'Tout est une arme'}
]
- HeroTokyo : héros dont la ville est Tokyo
HeroTokyo = select(Hero, "ligne['VilleHero'] == 'Tokyo'")
# Résultat :
# [{'NumHero': '3', 'NomHero': 'Ryo Saeba', 'VilleHero': 'Tokyo'},
# {'NumHero': '5', 'NomHero': 'Onizuka', 'VilleHero': 'Tokyo'}]
- HeroAlpha : héros triés par ordre alphabétique du nom
HeroAlpha = tri(Hero, 'NomHero')
# Résultat :
# [{'NumHero': '2', 'NomHero': 'Luffy', 'VilleHero': 'Fuchsia'},
# {'NumHero': '1', 'NomHero': 'Naruto', 'VilleHero': 'Konoha'},
# {'NumHero': '5', 'NomHero': 'Onizuka', 'VilleHero': 'Tokyo'},
# {'NumHero': '3', 'NomHero': 'Ryo Saeba', 'VilleHero': 'Tokyo'},
# {'NumHero': '4', 'NomHero': 'Saitama', 'VilleHero': 'Ville Z'},
# {'NumHero': '0', 'NomHero': 'Sangoku', 'VilleHero': 'Kyoto'}]
- HeroComplet : nom, ville et arme des héros (fusion puis projection)
HeroFusion = fusion(Hero, Armes, 'NumHero')
HeroComplet = projection(HeroFusion, ['NomHero', 'VilleHero', 'Arme'])
# Résultat :
# [{'NomHero': 'Sangoku', 'VilleHero': 'Kyoto', 'Arme': 'Ki'},
# {'NomHero': 'Naruto', 'VilleHero': 'Konoha', 'Arme': 'Chakra'},
# {'NomHero': 'Luffy', 'VilleHero': 'Fuchsia', 'Arme': 'Corps'},
# {'NomHero': 'Ryo Saeba', 'VilleHero': 'Tokyo', 'Arme': 'Magnum'},
# {'NomHero': 'Saitama', 'VilleHero': 'Ville Z', 'Arme': 'Poing'},
# {'NomHero': 'Onizuka', 'VilleHero': 'Tokyo', 'Arme': 'Tout est une arme'}]
- HeroVille : numéro et ville des héros
HeroVille = projection(Hero, ['NumHero', 'VilleHero'])
# Résultat :
# [{'NumHero': '0', 'VilleHero': 'Kyoto'},
# {'NumHero': '1', 'VilleHero': 'Konoha'},
# {'NumHero': '2', 'VilleHero': 'Fuchsia'},
# {'NumHero': '3', 'VilleHero': 'Tokyo'},
# {'NumHero': '4', 'VilleHero': 'Ville Z'},
# {'NumHero': '5', 'VilleHero': 'Tokyo'}]
- HeroImpair : nom et ville des héros ne venant pas de Tokyo et dont le numéro est impair
HeroImpair = select(Hero, "ligne['VilleHero'] != 'Tokyo' and int(ligne['NumHero']) % 2 == 1")
HeroImpair = projection(HeroImpair, ['NomHero', 'VilleHero'])
# Résultat :
# [{'NomHero': 'Naruto', 'VilleHero': 'Konoha'}]
Source : Florian Mathieu - Licence CC BY NC SA