À ce stade, nous avons un tableau contenant toutes les lettres de notre liste de mot. Ce tableau ne va pas directement nous être utile, nous allons plutôt utiliser une structure de données un peu plus complexe : les objets. Pour vous rafraichir la mémoire sur ce sujet, si nécessaire, je vous invite à consulter l'activité consacrée aux objets en JavaScript : ici
Petit rappel tout de même, un objet en JavaScript est de la forme :
obj={attribut1:valeur1,attribut2:valeur2,attribut3:valeur3}
Encore un rappel, pour accéder à la valeur de "attribut2" (c'est-à-dire "valeur2"), il est possible d'écrire :
obj.attribut2
mais il aussi possible d'écrire :
obj[attribut2]
Ces 2 écritures sont équivalentes , mais nous allons utiliser la seconde.
Notre objectif va être de placer les lettres, qui sont pour l'instant dans un tableau, dans un objet.
Au lieu d'avoir le tableau suivant :
["a"," ","à"," ","a","b","a","i","s","s","a"," ","a","b","a","i","s","s","a","b","l","e",...]
Nous aurons l'objet suivant :
{"a":xxx," ":xxx,"à":xxx,...}
Évidemment les valeurs des différents attributs ne seront pas des "x", nous reviendrons sur cette question un tout petit peu plus tard
Analysez et testez le code suivant :
var tabMots;
var chaineMots="";
var objLettres={};
function preload(){
tabMots=loadStrings("liste_mots.txt");
}
function setup(){
noCanvas;
for (i=0; i<tabMots.length;i++){
chaineMots=chaineMots+tabMots[i]+" ";
}
for (i=0;i<chaineMots.length;i++){
lettre=chaineMots.charAt(i);
if (!objLettres[lettre]){
objLettres[lettre]=[];
objLettres[lettre].push(chaineMots.charAt(i+1));
}
else {
objLettres[lettre].push(chaineMots.charAt(i+1));
}
}
createP ('La lettre "a" est suivi par les lettres : '+objLettres["a"]);
}
Vous devriez obtenir ceci :
Voici la partie difficile (et nouvelle) du code ci-dessus :
for (i=0;i<chaineMots.length;i++){
lettre=chaineMots.charAt(i);
if (!objLettres[lettre]){
objLettres[lettre]=[];
objLettres[lettre].push(chaineMots.charAt(i+1));
}
else {
objLettres[lettre].push(chaineMots.charAt(i+1));
}
}
Analysons cette portion de code :
Partons du principe que nous avons la chaîne de caractères "chaineMots" suivante :
chaineMots="a à abaissa"
La boucle "for" va nous permettre de parcourir l'ensemble de cette chaîne de caractères
Au premier tour de boucle, la variable "lettre" contient le caractère "a" (puisqu’au premier tour de boucle nous avons i=0, chaineMots.charAt(i) renvoi donc la premier caractère de la chaîne).
Le if (!objLettres[lettre]) permet de vérifier si l'objet "objLettres" possède déjà un attribut "a". Dans notre exemple ce n'est pas le cas (puisque jusqu'à présent l'objet "objLettres" est vide). Dans notre objet "objLettres" la valeur de l'attribut "a" sera un tableau pour le moment vide (objLettres[lettre]=[];). La ligne suivante (objLettres[lettre].push(chaineMots.charAt(i+1));) permet de placer le caractère qui suit "a" (un espace " " dans notre exemple) dans le tableau associé à "objLettres["a"]". A ce stade, nous avons :
objLettres={"a":[" "]}
Nous repartons au début de la boucle "for" et nous gérons le deuxième caractère de la chaîne : " " (un espace). Il n'existe pas encore d'attribut " " pour l'objet "objLettres", nous associons un tableau vide à cet attribut et nous plaçons le caractère suivant ("à") dans ce tableau, nous obtenons alors :
objLettres={"a":[" "]," ":["à"]}
3e tour de la boucle for :
objLettres={"a":[" "]," ":["à"],"à":[" "]}
4e tour de la boucle for :
Le caractère est de nouveau un espace, nous ne créons pas de nouveau tableau, mais nous ajoutons au tableau existant le caractère suivant (c'est-à-dire "a")
objLettres={"a":[" "]," ":["à","a"],"à":[" "]}
5e tour de la boucle for :
Le caractère est de nouveau un "a", nous ne créons pas de nouveau tableau, mais nous ajoutons au tableau existant le caractère suivant (c'est-à-dire "b")
objLettres={"a":[" ","b"]," ":["à","a"],"à":[" "]}
6e tour de la boucle for :
objLettres={"a":[" ","b"]," ":["à","a"],"à":[" "],"b":["a"]}
7e tour de la boucle for :
objLettres={"a":[" ","b","i"]," ":["à","a"],"à":[" "],"b":["a"]}
Afin de vérifier si vous avez bien compris, donnez la structure de l'objet après le tour 8 de la boucle "for"
Notre programme va donc construire un "immense" objet avec comme attributs les caractères rencontrés lors du parcourt de la chaîne "chaineMots" (et ses 336531 mots). La valeur de chaque attribut étant un tableau qui contient tous les caractères qui suivent l'attribut.
Modifiez le programme du "À faire vous-même 3.1" afin d'obtenir le tableau des caractères qui suivent la lettre "b"
Testez et analysez le programme ci-dessous
var tabMots;
var chaineMots="";
var motAlea="";
var objLettres={};
var nbLettre=8;
function preload(){
tabMots=loadStrings("liste_mots.txt");
}
function setup(){
noCanvas;
var bouton=createButton("Créer un mot");
bouton.mousePressed(creationMot);
for (i=0; i<tabMots.length;i++){
chaineMots=chaineMots+tabMots[i]+" ";
}
for (i=0;i<chaineMots.length;i++){
lettre=chaineMots.charAt(i);
if (!objLettres[lettre]){
objLettres[lettre]=[];
objLettres[lettre].push(chaineMots.charAt(i+1));
}
else {
objLettres[lettre].push(chaineMots.charAt(i+1));
}
}
}
function draw(){}
function creationMot(){
motAlea="";
motAlea=motAlea+random(objLettres[" "]);
for (i=1;i<nbLettre;i++){
var prev=motAlea.charAt(i-1);
prochain=random(objLettres[prev]);
while (prochain==" "){
prochain=random(objLettres[prev]);
}
motAlea=motAlea+prochain;
}
createP(motAlea);
}
Étudions la partie nouvelle du code :
function creationMot(){
motAlea="";
motAlea=motAlea+random(objLettres[" "]);
for (i=1;i<nbLettre;i++){
var prev=motAlea.charAt(i-1);
prochain=random(objLettres[prev]);
while (prochain==" "){
prochain=random(objLettres[prev]);
}
motAlea=motAlea+prochain;
}
createP(motAlea);
}
L'idée principale de cette portion de programme (et même de cette activité) est la suivante :
À chaque caractère rencontré dans la chaîne est associé un tableau, voici, par exemple une partie du tableau associé au "b" :
tab=["a","a","l","a","l","a","a","a","a","a","a",...]
Comme vous pouvez le constater, il y a 9 "a" et 2 "l". En nous basant sur cet exemple (qui n'est que partiel, pour avoir des valeurs représentatives il faudrait travailler sur l'ensemble du tableau associé au "b"), nous pouvons dire qu'en français, on rencontre plus souvent l'enchainement "ba" que l'enchaînement "bl".
Si nous faisons un random(tab), nous aurons le tirage aléatoire d'un des élèments du tableau "tab" avec 2 chances sur 11 d'avoir un "l" et 9 chances sur 11 d'avoir un "a", ce qui est tout à fait compatible avec le fait qu'en français nous rencontrons plus souvent l'enchainement "ba" que l'enchainement "bl".
Revenons au programme :
La fonction "creationMot" est exécutée en cas d'appui sur le bouton
Nous créons une chaîne de caractères vide : "motAlea"
Le random(objLettres[" "]); permet d'avoir une lettre pour commencer notre mot. Imaginons que ce tirage aléatoire donne la lettre "a" (nous avons alors motAlea="a").
Nous rentrons ensuite dans la boucle "for" avec i=1
La variable "prev" contient le caractère situé à la position "i-1" (c'est-à-dire à la position 0, c'est-à-dire le "a").
La variable "prochain" va contenir un caractère tiré au sort dans le tableau associé au caractère "a", imaginons que l'on tombe sur un "n", nous avons alors motAlea="an".
N.B : La boucle "while" permet d'éviter d'avoir un espace en plein milieu de notre mot.
2e tour de la boucle "for" :
"prev="n"", nous tirons au sort un caractère dans le tableau associé au "n"...je vous laisse imaginer la suite
Vous devriez obtenir ceci :
Comme vous pouvez le constater, nous obtenons de meilleurs résultats que dans le "À faire vous-même 2.1", mais ce n'est pas encore tout à fait satisfaisant, nous allons devoir procéder autrement !