mercredi 10 décembre 2014

9-TABLES de HACHAGE:

>>>>
Liste des symboles rencontrés dans ce chapitre:
make-hash-table hash-table-test hash-table-p gethash hash-table-count remhash push clrhash maphash 

Tables de hachage.

MAKE-HASH-TABLE:

(defparameter *h* (make-hash-table))
*H*             définit une table de hachage

(defparameter *h* (make-hash-table :test #'equal))
*H*             :test permet de préciser le test d'égalité des clés (par défaut: EQL)

(defparameter *h* (make-hash-table :size 5))
*H*        :size permet de préciser la taille de la table de hachage,en fait le nombre d'éléments (ici 5)

MAKE-HASH-TEST:

(hash-table-test *h*)
EQUAL rend le test d'égalité utilisé pour la table *h*

HASH-TABLE-P:

(hash-table-p *h*)
T pour vérifier si *h* est bien une table de hachage

GETHASH:        (permet de lire la valeur d'une clé d'une table de hachage)

(gethash 'foo *h*)
NIL                pas de valeur correspondant à la clé foo
NIL                NIL (le 2ème) indique que NIL n'est pas la valeur de foo

gethash est setfable: on peut définir une clé et lui donner une valeur.

(setf (gethash 'foo *h*) 'toto)
TOTO        définit la valeur TOTO pour la clé foo

(gethash 'foo *h*)
TOTO        rend la valeur TOTO à l'aide de la clé foo
T                T indique que la clé foo possède une valeur

Il faut bien noter que la 2ème valeur rendue par GETHASH indique si la clé est bien présente dans la table de hachage.
La valeur de cette clé pourrait être NIL.
La 2ème valeur est passée sous silence, à moins qu'un traitement explicite ne soit utilisé pour voir les valeurs multiples rendues. C'est le cas avec la macro MULTIPLE-VALUE-BIND qui crée des variables liées (comme LET):

(defun montre-valeur (clé table-hach)
  (multiple-value-bind (valeur present) (gethash clé table-hach)
    (if present
(format nil "La valeur ~a est présente dans la table de hachage." valeur)
(format nil "La valeur ~a est rendue car la clé n'est pas dans la table de hachage." valeur))))
MONTRE-VALEUR      définition de la fonction analysant la table de hachage

(setf (gethash 'bar *h*) nil)
NIL       introduction de la clé bar dans la table avec la valeur NIL

(montre-valeur 'foo *h*)
"La valeur TOTO est présente dans la table de hachage."

(montre-valeur 'bar *h*)
"La valeur NIL est présente dans la table de hachage."

(montre-valeur 'baz *h*)
"La valeur NIL est rendue car la clé n'est pas dans la table de hachage."

HASH-TABLE-COUNT:       (compte le nombre de clés dans la table de hachage)

(hash-table-count *h*)
2 il y a 2 clés dans la table de hachage *h*

REMHASH:        (pour effacer une clé)

(remhash 'bar *h*)
T                          efface la clé bar et sa valeur de la table de hachage
             NIL si la clé n'existe pas

(montre-valeur 'bar *h*)
"La valeur NIL est rendue car la clé n'est pas dans la table de hachage."

PUSH:   (utiliser pour donner une valeur à une clé)

(push "N'est pas habituellement utilisé comme fonction."
      (gethash 'boz *h*))
("N'est pas habituellement utilisé comme fonction.")
                        push permet d'entrer une clé et sa valeur

(gethash 'boz *h*)
("N'est pas habituellement utilisé comme fonction.")
T

CLRHASH:        (pour effacer le contenu d'une table de hachage)

(clrhash *h*)
#              efface toute la table

(montre-valeur 'foo *h*)
"La valeur NIL est rendue car la clé n'est pas dans la table de hachage."

Remarque: la table existe encore. Elle n'est pas supprimée.

Itération sur une table de hachage:

MAPHASH:      prend comme arguments une fonction à deux arguments et une table de hachage. Exemple:

(setf (gethash 'foo *h*) 'toto)     >>  TOTO
(setf (gethash 'bar *h*) 'tonton)   >>  TONTON
(setf (gethash 'baz *h*) 'tata)   >>  TATA

(maphash #'(lambda (clé val) (format t "~a => ~a~%" clé val)) *h*)
FOO => TOTO
BAR => TONTON
BAZ => TATA
NIL                           affiche toutes les clés et leurs valeurs

Autre exemple:

(setf (gethash 'foo *h*) 20)
20 On introduit des valeurs numériques

(setf (gethash 'bar *h*) 10)
10

(setf (gethash 'baz *h*) 5)
5

(maphash #'(lambda (clé val) (format t "~a => ~a~%" clé val)) *h*)
FOO => 20
BAR => 10
BAZ => 5
NIL                         On affiche ces valeurs

(maphash #'(lambda (clé val) (when (< val 10) (remhash clé *h*))) *h*)
NIL                         On supprime les valeurs inférieures à 10

(maphash #'(lambda (clé val) (format t "~a => ~a~%" clé val)) *h*)
FOO => 20
BAR => 10
NIL                         On affiche les valeurs restantes

Utilisation de LOOP:

(loop for clé being the hash-keys in *h* using (hash-value valeur)
     do (format t "~a => ~a~%" clé valeur))
FOO => 20
BAR => 10
NIL

Rem.: à la place de "the" on peut utiliser "each" et à la place de "in": "of".

_______________________________________________________
Exercice (résolu)
On construit une alist à partir d'une liste de clés et d'une liste de valeurs correspondantes.
Puis on cherche une fonction permettant la conversion de cette alist en table de hachage.
Voir alist: plus loin.

(defparameter l1 '(a b c d))
L1           définition de la liste de clés

(defparameter l2 '(1 2 3 4))
L2           définition de la liste de valeurs

(defparameter lst (mapcar #'cons l1 l2))
LST            construction de la alist

lst
((A . 1) (B . 2) (C . 3) (D . 4))                vérification

(defparameter *h* (make-hash-table))
*H* définition d'une table de hachage

(defun alist-vers-table-h (l)
  (if (endp l)
      t
      (progn (setf (gethash (caar l) *h*) (cdar l))
     (alist-vers-table-h (cdr l)))))
ALIST-VERS-TABLE-H     définition de la fonction convertissant la alist en table de hachage

(alist-vers-table-h lst)
T    rend T quand la table est construite

(gethash 'b *h*)
2
T vérification sur la clé b

(maphash #'(lambda (clé val) (format t "~a >>> ~a~%" clé val)) *h*)
A >>> 1
B >>> 2
C >>> 3
D >>> 4
NIL vérification avec MAPHASH

Autre exemple:

(defparameter lst1 '(0 1 2 3 4 5 6 7 8 9))
LST1

(defparameter lst2 '(zéro un deux trois quatre cinq six sept huit neuf))
LST2

(defparameter alst (mapcar #'cons lst1 lst2))
ALST
La alist est construite

(defparameter *hnb* (make-hash-table))
*HNB*

(alist-vers-table-h alst *hnb*)
T
La table de hachage est construite

(maphash #'(lambda (clé val) (format t "~a >>> ~a~%" clé val)) *hnb*)
0 >>> ZÉRO
1 >>> UN
2 >>> DEUX
3 >>> TROIS
4 >>> QUATRE
5 >>> CINQ
6 >>> SIX
7 >>> SEPT
8 >>> HUIT
9 >>> NEUF
NIL

prochainement: "Compléments sur quelques fonctions."

Aucun commentaire:

Enregistrer un commentaire