Précédent Index Suivant

Liste d'associations

 

 
Une liste d'associations est une liste dont chaque terme est une association clef-valeur: chaque terme de la liste d'associations est un couple (c'est-à-dire un n-uplet ayant deux éléments) dont le premier élément est la clef et le second la valeur. Ainsi, étant donnés deux types -- Clef et Valeur -- une association est un élément de type NUPLET[Clef Valeur] et une liste d'associations est un élément de type LISTE[NUPLET[Clef Valeur]].
 
Voici un exemple d'association:
 
;;; l'expression suivante est une association de type NUPLET[nat string] 
(list 1 "un")
 

 
(à 1, on associe ``un'', ou encore la clef est 1 et la valeur est ``un'').
 
Un exemple d'une liste d'associations:
 
;;; l'expression suivante est une liste d'associations de type  
;;; LISTE[NUPLET[nat string]] 
(list (list 1 "un") (list 2 "deux") (list 3 "trois"))
 

 
(à 1, on associe ``un'', à 2, on associe ``deux'', à 3, on associe ``trois'')
 
Ajout dans une liste d'associations  
La fonction ajout ajoute un couple á cle, valeurñ à une liste d'associations donnée. Par exemple:  
(ajout 3 "trois" (list)) -> ((3 "trois"))
 
(ajout 1 "un" (ajout 2 "deux" 
                     (ajout 3 "trois" (list))))

--> ((1 "un") (2 "deux") (3 "trois"))
 
(let* ((L1 (ajout 3 "trois" (list)))
       (L2 (ajout 2 "deux" L1))
       (ma-L (ajout 1 "un" L2)))
  (ajout 2 "two" ma-L))

--> ((2 "two") (1 "un") (2 "deux") (3 "trois"))  

 
elle peut être définie par:  
;;; ajout : a * b * LISTE[N-UPLET[a b]] -> LISTE[N-UPLET[a b]] 
;;; (ajout clef valeur a-liste) rend la liste d'associations obtenue en ajoutant 
;;; l'association « (clef valeur) » en tête de la liste d'associations «a-liste». 
(define (ajout clef valeur a-liste)
  (cons (list  clef valeur)
        a-liste))
 

 
Recherche dans une liste d'associations  
La fonction de recherche dans une liste d'associations est une primitive de Scheme, qui a pour nom assoc. Son objectif est de rechercher la première association de la liste qui a une clef donnée. Notons que, pour des raisons d'efficacité, l'ajout d'une nouvelle association se fait en tête de liste. Du coup, lors d'une recherche, on rend toujours l'association la plus récente pour une clef donnée. C'est un semi-prédicat: elle rend #f lorsqu'une telle association n'existe pas, et lorsqu'elle existe, elle rend la valeur « vrai » sous une forme plus informative, à savoir l'association elle-même:
 
- lorsque la clef n'existe pas:  
(assoc 2 (ajout 3 "trois" (list)))

--> #f  

 
- lorsque la clef existe une fois:  
(let* ((L1 (ajout 3 "trois" (list)))
       (L2 (ajout 2 "deux" L1))
       (ma-L (ajout 1 "un" L2)))
  (assoc 2 ma-L))

--> (2 "deux")  

 
- lorsque la clef existe plusieurs fois:  
(let* ((L1 (ajout 3 "trois" (list)))
       (L2 (ajout 2 "deux" L1))
       (ma-L (ajout 1 "un" L2)))
  (assoc 2 (ajout 2 "two" ma-L)))

--> (2 "two")  

 
Rappelons que assoc est une primitive de Scheme. Elle pourrait être définie par:  
;;; assoc : a * LISTE[N-UPLET[a b]] -> N-UPLET[a b] + #f 
;;; (assoc clef aliste) rend la première association de «aliste» dont le premier  
;;; élément est égal à «clef». Rend la valeur #f en cas d'echec. 
(define (assoc clef aliste)
  (if (pair? aliste)
      (if (equal? clef (caar aliste))
          (car aliste)
          (assoc clef (cdr aliste))) 
      #f))
 

 
On peut aussi vouloir définir la fonction valeur-de qui donne la valeur associée à une clef. Par exemple:
 
(valeur-de 2 (ajout 3 "trois" (list))) -> #F  

 
(let* ((L1 (ajout 3 "trois" (list)))
       (L2 (ajout 2 "deux" L1))
       (ma-L (ajout 1 "un" L2)))
  (valeur-de 2 ma-L))
--> "deux"  

 
Cette fonction peut être définie par:
 
;;; valeur-de : a * LISTE[N-UPLET[a b]] -> b + #f 
;;; (valeur-de clef aliste) rend la valeur de la première association de «aliste»  
;;; dont le premier élément est égal à «clef». Rend #f en cas d'echec. 
(define (valeur-de clef aliste)
  (let ((couple (assoc clef aliste)))
    (if couple 
        (cadr couple)
        #f)))
 

 
Rappel: dans une forme conditionnelle, toute condition qui n'a pas la valeur #f a une valeur de vérité Vrai.
 
Exemple d'utilisation des listes d'associations  
Un dictionnaire français-anglais permet de traduire une phrase française (vue comme une suite de mots) en anglais. Il peut être implanté par une liste d'association:  
(("chat" "cat") ("chien" "dog") ("souris" "mouse"))  

 
Le problème est alors de traduire (mot à mot) une phrase française (implantée par une liste de mots) en anglais:
 
(let ((mon-dico (list (list  "chat" "cat") 
                      (list "chien" "dog") 
                      (list "souris" "mouse")
                      (list "manger" "eat")
                      (list "fromage" "cheese")))
      (phr1 (list "souris" "manger" "fromage"))
      (phr2 (list "chat" "manger" "souris")))
  (write (traduction mon-dico phr1))
  (write (traduction mon-dico phr2)))
--> ("mouse" "eat" "cheese")("cat" "eat" "mouse")  

 
Avant d'écrire la fonction traduction, on peut écrire des fonctions plus simples. Par exemple, dico-french rend la liste des mots français du dictionnaire donné:
 
(let ((mon-dico (list (list  "chat" "cat") 
                      (list "chien" "dog") 
                      (list "souris" "mouse"))))
  (dico-french mon-dico))
--> ("chat" "chien" "souris")  

 
Cette fonction se définit facilement avec un map:
 
;;; dico-french : Dico -> LISTE[string] 
;;; où Dico est égal à LISTE[N-UPLET[string string]], le premier string  
;;; étant le mot français et le second string étant le mot anglais 
;;; (dico-french dico) rend la liste des mots français du dictionnaire «dico» donné.  
(define (dico-french dico)
  (map car dico))
 

 
Pour définir la fonction dico-anglais qui permet de connaître la liste des mots anglais présents dans un dictionnaire, on peut aussi utiliser un map:
 
;;; dico-anglais : Dico -> LISTE[string] 
;;; où Dico est égal à LISTE[N-UPLET[string string]], le premier string  
;;; étant le mot français et le second string étant le mot anglais 
;;; (dico-anglais dico) rend la liste des mots anglais du dictionnaire «dico» donné.  
(define (dico-anglais dico)
  (map cadr mon-dico))
 

 
Écrivons maintenant la fonction traduction. Il suffit de faire un map avec la fonction qui traduit un mot. Cette dernière est essentiellement la fonction valeur-de que nous avons définie plus haut, le seul problème étant que cette dernière a un argument de trop (le dictionnaire). Pour résoudre ce (petit) problème, il suffit de définir une fonction interne à la définition de la fonction traduction:
 
;;; traduction : Dico * LISTE[string] -> LISTE[string] 
;;; où Dico est égal à LISTE[N-UPLET[string string]], le premier string  
;;; étant le mot français et le second string étant le mot anglais 
;;; (traduction dico phrase) rend la liste de mots «phrase», traduite selon  
;;; le dictionnaire «dico» 
(define (traduction dico phrase)  
  (define (traduction-mot m)
    (valeur-de m dico))
  (map traduction-mot phrase))
 

 



Auteur(s): titou@ufr-info-p6.jussieu.fr.Mainteneur de la page: titou@ufr-info-p6.jussieu.fr.

Précédent Index Suivant