NSI (première) · Chapitre 5 · Exercice de TD
Écrire inverse(d) qui échange clés et valeurs
Les dictionnaires · Construire, lire, modifier · niveau 2
Énoncé
Écrire inverse(d) qui échange clés et valeurs. Tester avec {"a": 1, "b": 2}, puis avec {"a": 1, "b": 1}. Que se passe-t-il ? Le dire dans la docstring plutôt que de le laisser au lecteur — puis écrire inverse_complet qui ne perd rien.
Corrigé
def inverse(d):
"""Echange cles et valeurs de d.
Precondition : les valeurs de d peuvent servir de cles (non modifiables).
Postcondition : si deux cles de d ont la MEME valeur, une seule survit --
la derniere rencontree. Le resultat a donc au plus
len(d) entrees, et strictement moins en cas de doublon.
"""
resultat = {}
for cle, valeur in d.items():
resultat[valeur] = cle
return resultat
L'inversion perd de l'information, et c'est structurel. Les clés sont uniques, les valeurs non : c'est la toute première remarque du chapitre. En inversant, les anciennes valeurs deviennent des clés — et le dictionnaire, qui n'accepte pas deux fois la même clé, en garde une seule. Sur {"a": 1, "b": 1}, le résultat est {1: "b"} : "a" a disparu, sans erreur ni avertissement. Le dictionnaire des âges du cours, où Nour et Yanis ont tous deux 17 ans, perd donc un élève.
La précondition n'est pas décorative. Les valeurs deviennent des clés : elles doivent donc être non modifiables. inverse({"x": [1, 2]}) lève TypeError: unhashable type: 'list' — l'inversion échoue sur un dictionnaire parfaitement valide, uniquement à cause de ses valeurs.
def inverse_complet(d):
"""Echange cles et valeurs SANS rien perdre : chaque valeur donne la
liste des cles qui lui etaient associees.
Postcondition : la somme des longueurs des listes du resultat vaut len(d).
"""
resultat = {}
for cle, valeur in d.items():
if valeur in resultat:
resultat[valeur].append(cle)
else:
resultat[valeur] = [cle]
assert sum(len(v) for v in resultat.values()) == len(d)
return resultat
La postcondition qui interdit la perte. sum(len(v) ...) == len(d) est exactement l'énoncé « rien n'a été perdu ». C'est la même postcondition que occurrences dans le cours, et elle joue le même rôle : elle rend l'oubli impossible à ignorer. Notez qu'aucune postcondition de ce genre ne peut être écrite pour inverse — c'est le signe qu'elle perd quelque chose.
Vérification.
assert inverse({"a": 1, "b": 2}) == {1: "a", 2: "b"}
assert inverse({"a": 1, "b": 1}) == {1: "b"} # "a" a DISPARU
assert len(inverse({"a": 1, "b": 1})) == 1
ages = {"Nour": 17, "Camille": 16, "Yanis": 17}
assert inverse(ages) == {17: "Yanis", 16: "Camille"}
assert inverse_complet(ages) == {17: ["Nour", "Yanis"], 16: ["Camille"]}100 % gratuit
Essaie le suivant avec le tuteur
- L'exercice suivant avec le tuteur, sans compte : il guide pas à pas, sans donner la réponse
- 16 autres exercices corrigés dans ce chapitre, et 20 à chercher avec le tuteur
- Le podcast et la vidéo du chapitre et la correction filmée du TD : 2 minutes sans compte
Sans compte : le cours, 2 minutes de podcast et de vidéo et un exercice avec le tuteur. Pour tout le reste : inscription gratuite en 30 secondes, sans carte bancaire.