Comprendre les tableaux (Array)
Voici qui s'adresse à ceux que le mot tableau rebute.
Extraits tous chauds du forum : “C'est peut-être un peu long, mais les tableaux je les fuis comme la peste” … “Ah oui, un tableau… Mais je débute, je n'y comprends rien !”
A ceux là, et à tous ceux qui s'y reconnaitront, je dis : trop dommage !
Les tableaux, c'est pratique et pas si difficile que ça, voire pas difficile du tout. Vous avez déjà croisé une commode dans votre vie ? Et quand on vous a dit “Va chercher dans le tiroir du haut”, vous y êtes arrivé que je sache ?
Et ben voilà, vous savez utiliser les tableaux
Donc on peut commencer.
Pour démarrer : créer, remplir et lire
Ce qu'il faut savoir, c'est que dans un tableau on peut ranger ce qu'on veut (ou presque), des données de tous types : int, String, Booleen, Object, Shape, en passant par MovieClip et même des tableaux…
Un tableau en ActionScript (et un paquet d'autre langages ), ça se dit Array
Et comme pour tous les objets, pour les utiliser encore faut il les créer.
Donc une variable tbEssai
de type Array…
var tbEssai:Array;
… qui vaut quoi ? un nouveau tableau :
var tbEssai:Array = new Array();
Nous voilà avec une commode vide, ou plus exactement, une commode sans tiroirs.
Ce qui est pratique, c'est que les tiroirs se fabriquent au fur et à mesure des besoins.
On ajoute un élément dans un tableau à l'aide de la méthode push.
tbEssai.push("Pierre");
…vous venez d'ajouter la chaine “Pierre” dans tbEssai.
tbEssai.push("Paul");
Qu'est ce que ça donne ? Regardons :
trace(tbEssai); // Pierre,Paul //Encore un… tbEssai.push("Jacques"); trace(tbEssai); // Pierre,Paul,Jacques // plusieurs d'un coup : tbEssai.push("Marie","Madeleine","Claude") trace(tbEssai); //Pierre,Paul,Jacques,Marie,Madeleine,Claude
J'ai introduit l'histoire en parlant de commode et de tiroirs mais on ne va pas bêtifier pendant trois pages non plus donc :
Un tiroir, c'est un emplacement et un emplacement est identifié par un numéro d'index.
C'est pas plus dur que ça.
Ça donne : Pierre est au n° 0 (ah oui : on commence à zéro !), Paul au 1, et Jacques au 2.
Du coup, c'est tout niais d'aller lire ou récupérer l'élément de son choix dès lors qu'on connait son numéro d'index (et la syntaxe )
On accède à un élément d'un tableau (lecture/écriture) avec la syntaxe à crochets, soit :
leTableau[n°Index]
var tbEssai:Array = new Array(); tbEssai.push("Pierre"); tbEssai.push("Paul"); tbEssai.push("Jacques"); // lecture : trace(tbEssai[0]); // Pierre // écriture : tbEssai[0]="Manon"; trace(tbEssai); // Manon,Paul,Jacques
Jusque là, ça va ?
L'autre truc utile qu'on connait par cœur, c'est la propriété length qui renvoie le nombre d'éléments du tableau.
Attention : pas l'index du dernier.
ici, tbEssai.length renvoie 3 mais Jacques (le dernier) est en 2. On commence à zéro… souvenez vous…
Exemple 1 : J'ai perdu mes clips
Bon, et bien avec cette poignée d'outils, déjà, on a tout pour répondre à celles et ceux qui sont là parce qu'ils ont “perdu les clips dans une boucle”.
Imaginons la consigne simple suivante (on va pas non plus se faire dactylo tout de suite) :
On veut créer 10 instances depuis un symbole de bibliothèque, puis dans un premier temps, n'afficher (addChild) que le premier.
Si vous voulez jouer, construisez un clip minimaliste dans la bibliothèque, un rectangle et un champ texte dynamique txt
(on va les numéroter au passage pour y voir clair). Nommez ce clip Elt
et cochez la case exporter pour actionScript.
Mauvaise technique
for (var i=0; i<10; i++) { // créer nouvelle instance de Elt var clip:Elt=new Elt(); // Numéroter clip.txt.text=String(i); } // Ajouter à la liste d'affichage addChild(clip); clip.x=clip.y=150
C'est le clip 9 qui s'affiche, pas le 0
Normal :
A chaque tour de boucle la variable clip référence un nouveau clip (new
), et forcément, le précédent est perdu
Disons le autrement : une variable c'est une ficelle accrochée à une donnée (objet, valeur), je tire la ficelle, je chope la donnée ou l'objet. Ici à chaque tour de boucle on détache la ficelle du précédent clip et on l'accroche au suivant… Si on détache le chien de sa laisse, il se sauve et on pourra toujours courir.
Donc là, on a une laisse pour dix chiens, ça en fait neuf dans la nature.
Comment faire ?
Tiens, filons la métaphore : les chiens pour ne pas les perdre, on va les ranger à la niche, au fur et à mesure de leur création. En l'espèce, la niche c'est un tableau.
// Un tableau var tbElt:Array= new Array(); for (var i=0; i<10; i++) { var clip:Elt=new Elt(); clip.txt.text=String(i); // Ranger le clip dans un tableau tbElt.push(clip); } // Ajouter le clip "rangé" au numéro d'index 0 du tableau addChild(tbElt[0]); tbElt[0].x=tbElt[0].y=150
Pas très fin d'appeler trois fois tbElt[0], c'est juste pour qu'on soit bien d'accord sur le fait que la syntaxe crochets renvoie une référence à ce qui est stocké au numéro d'index, utilisable comme tel.
En plus mieux :
var tbElt:Array= new Array(); for (var i=0; i<10; i++) { var clip:Elt=new Elt(); clip.txt.text=String(i); tbElt.push(clip); } // pour changer, on affiche le n° 4 var leClip:MovieClip=tbElt[4] addChild(leClip); leClip.x=leClip.y=150
Autres possibilités de création
Jusque là on sait :
• créer un tableau : monTableau = new Array()
• remplir un tableau monTableau.push(…)
• lire et écrire dans un tableau monTableau[…]
• compter le nombre d'éléments dans un tableau : monTableau.length
Pour créer un tableau, il y a d'autres techniques. On peut déclarer et valoriser le tableau, “d'un coup”.
var monTableau:Array=new Array("Pierre","Paul","Jacques"); var tbCoordonnéesX:Array=new Array(50,70,75,125,130);
Il suffit de passer, entre parenthèses et séparés par une virgule, les différents éléments du tableau.
Les éléments peuvent être de types différents.
var tb1:Array= new Array(50,-12,100,0.5,"25",true);
Notez cependant que tous les “nombres” seront typés Number :
for (var i:int=0; i<T1.length; i++) { trace(T1[i]); trace("-->" + typeof T1[i]); }
50 -->number -12 -->number 100 -->number 0.5 -->number 25 -->string true -->boolean
Et enfin, on peut se passer du 'new Array' et écrire tout bonnement :
var leTableau:Array=["un truc","un autre",18,false]
Attention ! Piège…
Il pourrait se produire qu'un jour on ait l'idée de créer un tableau avec une seule entrée, pour commencer, avec le projet de le remplir par la suite. Par exemple :
var tbEssai:Array= new Array("Pierre"); // […] // un peu plus tard : tbEssai.push("Paul"); tbEssai.push("Jacques"); trace(tbEssai);
Pierre,Paul,Jacques
Avec des int maintenant :
var tbEssaiInt:Array= new Array(5); // un peu plus tard : tbEssaiInt.push(18); tbEssaiInt.push(22); trace(tbEssaiInt);
,,,,,18,22
Ah bah zutalors !
Hé oui, c'est une autre façon de créer un tableau :
var tb:Array= new Array(Taille);
On lui assigne une taille, mais les entrées sont vides.
En vrai c'est ce qu'on fait avec la toute première technique (constructeur on dit). Quand on écrit :
monTableau = new Array();
On crée un tableau de taille 0.
la doc le dit :
public function Array(numElements:int = 0)
Comprendre : numElements
est de type int
et vaut 0 par défaut (si on ne le renseigne pas)
Un tableau depuis un chaîne de caractères
Une dernière chose : vous pouvez obtenir un tableau de chaines (String) en utilisant la méthode split de la classe String.
En français : si vous appliquez la méthode split à une chaine de caractères (en lui passant un séparateur) vous obtiendrez un tableau.
par exemple :
var lesNoms:String="Pierre#Paul#Jacques" var tbNoms:Array= lesNoms.split("#") trace(tbNoms) var lesJours:String="lundi mardi mercredi jeudi vendredi samedi dimanche" var tbJours:Array= lesJours.split(" ") trace(tbJours)
Pierre,Paul,Jacques lundi,mardi,mercredi,jeudi,vendredi,samedi,dimanche
On se résume
Pour créer un tableau deux constructeurs possibles :
• Avec un nombre spécifié d'éléments
public function Array(numElements:int = 0)
var tb:Array= new Array(6);// six emplacements vides
• Avec des valeurs (séparées par des virgules)
public function Array(… values)
var monTableau:Array=new Array("Pierre","Paul","Jacques");
… et un “raccourci” : directement avec des crochets sans le mot new.
var leTableau:Array=["un truc","un autre",18,false]
On peut aussi utiliser la méthode split(…) sur une chaine.
Ajouter : push(…)
Lecture écriture : tb[…]
Taille : length
Si arrivé là, vous vous dites : “Et bien, rien de bien sorcier là dedans…”, sachez que le reste est de la même eau
Lire les tableaux
join
Tout de suite, et puisque nous venons de parler de la méthode split qui renvoie un tableau depuis une chaine, voyons immédiatement la méthode qui fait le contraire, à savoir renvoyer une chaine depuis un tableau.
Il s'agit donc de la méthode join à qui on passe comme paramètre un caractère qui séparera les éléments de la chaine.
var tbEssai:Array=new Array("Madeleine","Valérie","Sophie","Pierre"); var laChaine:String=tbEssai.join(" et "); trace(laChaine);
Madeleine et Valérie et Sophie et Pierre
Oui… Je dis un caractère et j'exemplifie à l'aide d'une chaine… je sais mais c'était trop compliqué à formuler
En vrai de vrai, on peut passer n'importe quoi comme séparateur, une chaine, un int, de l'objet… ce qu'on veut. Le séparateur sera au passage converti en chaine
indexOf / lastIndexOf
Ou, comment retrouver le numéro d'index d'un élément de tableau…
Maintenant que vous avez apprivoisé l'animal tableau, certainement mes commentaires sont-ils superflus. Les noms des méthodes parlent d'eux même, pour peu qu'on ait quelques notions d'anglais (…mais quand même : indexDe, dernierIndexDe… même moi je me passe de dico ) :
var tbEssai:Array= new Array("Madeleine","Valérie","Sophie","Pierre","Anne","Denise","Madeleine","Bertrand"); trace(tbEssai.indexOf("Sophie")) //--> 2 trace(tbEssai.lastIndexOf("Madeleine")) //--> 6 trace(tbEssai.indexOf("Madeleine")) //--> 0 trace(tbEssai.lastIndexOf("Portnawak")) //--> -1 trace(tbEssai.indexOf("Portnawak")) //--> -1
Ces quelques lignes permettent de préciser les choses :
indexOf, renvoie le premier numéro d'index correspondant à l'élément spécifié.
lastIndexOf, renvoie le dernier numéro d'index correspondant à l'élément spécifié.
Si aucune correspondance n'est trouvée, c'est -1 qui est renvoyé, pour l'une comme l'autre (méthode )
Exemple 2 : je veux traduire une date
Tiens, histoire de se détendre :
On disait qu'on trainait sur le forum Mediabox et que l'on rencontrait cette question : Je voudrais traduire des noms de mois d'anglais en français…
Plusieurs pistes sont proposées, dont un switch qui vous semble vraiment excessif :
switch(month) { case "January" : month = "janvier" break; case "February" : month = "février" break; case "March" : month = "mars" //etc...
Je vous laisse chercher une solution plus élégante ? (avec des jours, ce sera moins de dactylo… )
Indice, voici les tableaux :
var tbJoursAng:Array= new Array("Monday","Tuesday","Wenesday","Thursday","Friday","Saturday","Sunday"); var tbJoursFr:Array= new Array("Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi","Dimanche");
A vous de jouer ! Oui : c'est à base d'indexOf…
var idxJourAnglais:int=tbJoursAng.indexOf("Tuesday") trace(tbJoursFr[idxJourAnglais])
Manipuler les tableaux
Parfait, maintenant que je vous sens bien en jambes, allons y pour un premier ensemble de méthodes qui nous permettront de jongler avec les éléments des tableaux.
Trier
Quand on trie un tableau ce dernier est modifié afin de refléter l'ordre de tri.
sort
Si vous souhaitez réorganiser les éléments d'un tableau selon leur valeur, vous utiliserez la méthode sort(…).
Utilisée sans arguments, le tri se fera selon les critères suivants :
• la casse (Majuscule précède minuscules)
• ordre alphabétique ascendant (a précède b)
var tb:Array= new Array("Paris","Lyon","marseille","bordeaux"); tb.sort(); trace(tb);
Lyon,Paris,bordeaux,marseille
Attention
Dans ce cas (sans arguments) quelque soit le type de données des éléments, ils seront triés comme s'il s'agissait de chaînes.
Ainsi, 200 est-il traité comme “200”, 3 comme “3”, 10 comme “10”… En conséquence 200 sera placé avant 3 mais après 10 !
var tb:Array=new Array(350,10,3,200); tb.sort(); trace(tb);
10,200,3,350
Heureusement pour nous, des arguments sont prévus pour préciser les conditions de tri, ce sont des constantes que voici :
• Array.CASEINSENSITIVE (insensible à la case)
• Array.DESCENDING (décroissant)
• Array.NUMERIC (numérique)
var tb:Array= new Array("Paris","Lyon","marseille","bordeaux"); tb.sort(Array.CASEINSENSITIVE); trace(tb);
bordeaux,Lyon,marseille,Paris
var tb:Array= new Array("Paris","Lyon","marseille","bordeaux"); tb.sort(Array.CASEINSENSITIVE | Array.DESCENDING); trace(tb);
Paris,marseille,Lyon,bordeaux
Notez le caractère “|” pour utiliser plusieurs options.
var tb:Array=new Array(350,10,3,200); tb.sort(Array.NUMERIC); trace(tb);
A Noter :
Les éléments dont les valeurs sont identiques seront placés consécutivement.
Si vous souhaitez intercepter les cas de doublons vous utiliserez :
• Array.UNIQUESORT ()
Si il y a doublons, le tableau ne sera pas trié, et la méthode renvoie 0, dans le cas contraire elle renvoie le tableau trié (et le trie… )
var tb:Array=new Array(350,10,3,200,10); var r:*=tb.sort(Array.NUMERIC | Array.UNIQUESORT); trace("renvoie "+r); trace("r==0 "+(r==0)); trace("tb = " +tb); if (r==0) { trace("doublons"); }
renvoie 0 r==0 true tb = 350,10,3,200,10 doublons
var tb:Array=new Array(350,10,3,200,100); var r:*=tb.sort(Array.NUMERIC | Array.UNIQUESORT); trace("renvoie "+r); trace("r==0 "+(r==0)); trace("tb = " +tb); if (r==0) { trace("doublons"); }
renvoie 3,10,100,200,350 r==0 false tb = 3,10,100,200,350
• Array.RETURNINDEXEDARRAY
Avec cette option le tableau n'est pas modifié… mais la méthode renvoie un tableau qui reflète les résultats du tri avec les index d'origine :
var tb:Array=new Array("Claude","Anne","Denise","Bertrand"); trace(tb.sort(Array.RETURNINDEXEDARRAY));
1,3,0,2
sortOn
Cette méthode est très proche de sort
, à la nuance près qu'elle trie “sur”…
sur quoi ?
sur un champ.
Je m'explique : On a vu que dans un tableau on pouvait mettre ce qu'on veut et notamment des objets (ce qui tombe bien pour un langage orienté objet ).
Ça ne mange pas de pain de vérifier
// un objet var oMembre:Object; // on le valorise oMembre={nom:"Durand",prenom:"Pierre",age:28}; // on lit la propriété nom de oMembre trace(oMembre.nom); // --> Durand // l'objet dans un tableau var tbMembres:Array=new Array(oMembre); // lire la propriété 'nom' de l'objet à l'index 0 trace(tbMembres[0].nom); // --> Durand
Imaginons un tableau de membres, le trier, c'est gentil, mais en fonction de quoi ? C'est là qu'on dégaine sortOn
et on lui passe une chaine qui vaut la propriété sur laquelle on souhaite trier. Dans ce cas, on parlera de champ.
Ajoutez donc deux membres :
tbMembres.push({nom:"Martin",prenom:"Paul",age:30}); tbMembres.push({nom:"Leroy",prenom:"Jacques",age:19});
On se propose de les trier sur les prénoms :
tbMembres.sortOn("prenom"); for (var i=0; i<tbMembres.length; i++) { trace(tbMembres[i].nom+" "+tbMembres[i].prenom+" "+tbMembres[i].age); }
Leroy Jacques 19 Martin Paul 30 Durand Pierre 28
Et sur l'âge ?
A vous de jouer
On attend :
Leroy Jacques 19 Durand Pierre 28 Martin Paul 30
tbMembres.sortOn("age", Array.NUMERIC); for (var i=0; i<tbMembres.length; i++) { trace(tbMembres[i].nom+" "+tbMembres[i].prenom+" "+tbMembres[i].age); }
Bon, d'accord je l'ai pas dit : on dispose des mêmes options de tri qu'avec la méthode sort. Vous vous êtes fait ruser, vous avez oublié Array.NUMERIC ? Chic, vous vous en souviendrez
Du coup pas grand chose à ajouter : pour les options de tri, reportez vous à la méthode sort (ou à la doc ).
Précisons quand même que les clips étant des objets vous pouvez, par conséquent, trier un tableau de clips selon n'importe quelle propriété des clips.
tbClips.sortOn(“x”,Array.Numeric);
reverse
Pour finir, reverse inverse l'ordre des éléments d'un tableau, rien à en dire.
var tb:Array= new Array("Machin",true,18,false); var tbEnvers:Array=tb.reverse() trace(tbEnvers);
false,18,true,Machin
Ajouter / Supprimer
Pour en finir avec push
On sait déjà ajouter à l'aide de la méthode push qui ajoute en fin de tableau. Il se trouve qu'elle renvoie au passage la nouvelle taille. Ça peut être pratique :
var max:int=tbQuelconque.push(…) // pas utile d'aller chercher tbQuelconque.length, push renvoie la taille ;-) for (var i:int=0;i<max;i++) { //traitements }
unshift
La copine c'est unshift, qui ajoute un (ou plusieurs) élément(s) au début d'un tableau, et renvoie tout pareil la taille du tableau.
var tbEssai:Array= new Array("Marie","Madeleine","Claude"); tbEssai.unshift("Pierre","Paul") trace(tbEssai);
Pierre,Paul,Marie,Madeleine,Claude
splice
Pour faire la transition entre les méthodes qui ajoutent et celles qui suppriment, voici splice qui ajoute et/ou supprime depuis un index spécifié - index compris.
splice(startIndex:int, deleteCount:uint, … values):Array
Elle attend
• startIndex
un numéro d'index, c'est là qu'on commence.
• deleteCount
combien d'éléments concernés par la suppression
0 : pour aucune suppression rien : tout supprimer jusqu'à la fin
• value
: le ou les élément(s) à ajouter
Ajouter Marie entre Pierre et Paul
var tbEssai:Array= new Array("Pierre","Paul","Jacques"); // Ça se passe index 1, on ne supprime rien du tout, on ajoute "Marie" tbEssai.splice(1,0,"Marie") trace(tbEssai);
Pierre,Marie,Paul,Jacques
Ajouter Madeleine et Claude entre Marie et Paul
// Ça se passe index 2, on ne supprime rien du tout, on ajoute "Madeleine","Claude" tbEssai.splice(2,0,"Madeleine","Claude") trace(tbEssai);
Pierre,Marie,Madeleine,Claude,Paul,Jacques
Remplacer Claude par Valérie
// index 3, on supprime un élément (Claude), on ajoute (remplace donc par) "Valérie" tbEssai.splice(3,1,"Valérie") trace(tbEssai);
Pierre,Marie,Madeleine,Valérie,Paul,Jacques
Supprimer Marie, Madeleine et Valérie (et les récupérer)
// index 1, on supprime trois éléments (depuis 1 inclus) var tbRecup:Array=tbEssai.splice(1,3) trace(tbEssai); //--> Pierre,Paul,Jacques trace(tbRecup); //--> Marie,Madeleine,Valérie
Comme illustré ci-dessus, splice renvoie un tableau des éléments supprimés.
pop et shift
Ces deux méthodes suppriment un élément (et renvoient l'élément supprimé).
pop supprime à la fin, shift au début.
Supprime dernier, pop :
var tbEssai:Array= new Array("Pierre","Paul","Jacques"); var nom:String=tbEssai.pop() trace(tbEssai); //--> Pierre,Paul trace(nom) //--> Jacques
Supprime premier, shift :
var tbEssai:Array= new Array("Pierre","Paul","Jacques"); var nom:String=tbEssai.shift() trace(tbEssai); //--> Paul,Jacques trace(nom) //--> Pierre
Mélanger
La classe Array ne nous donne pas de méthode spécifique pour mélanger les entrées d'un tableau, il faut le faire à l'huile de phalanges.
Il y a quantité de façons de s'y prendre, plus ou moins gourmandes. Badwolf propose dans cette conversation une technique très performante, (ne vous privez pas de lire les messages suivants)
Créer un nouveau tableau
concat
Concatène (mélange) deux tableaux en un.
var tbNouveau:Array=tb1.concat(tb2)
var tbGarcons:Array= new Array("Pierre","Paul","Jacques"); var tbFilles:Array= new Array("Madeleine","Valérie","Sophie"); var tabGarconsFilles:Array=tbGarcons.concat(tbFilles) trace(tabGarconsFilles);
Pierre,Paul,Jacques,Madeleine,Valérie,Sophie
var tbGarcons:Array= new Array("Pierre","Paul","Jacques"); var tbFilles:Array= new Array("Madeleine","Valérie","Sophie"); var tabGarconsBool:Array=tbGarcons.concat(true,false,false) trace(tabGarconsBool);
Pierre,Paul,Jacques,true,false,false
slice
Renvoie un nouveau tableau à partir d'une sélection d'éléments sans modifier le tableau d'origine.
slice(startIndex:int = 0, endIndex:int = 16777215):Array
On lui passe un index de départ qui sera inclus dans le nouveau tableau et un index d'arrivée, qui sera exclu.
var tbEssai:Array= new Array("Madeleine","Valérie","Sophie","Pierre","Anne","Denise","Bertrand"); // on veux Valérie,Sophie,Pierre // de Valérie (1) à Anne Exclue (4) var tbNouveau:Array=tbEssai.slice(1,4) trace(tbNouveau)
Valérie,Sophie,Pierre
Sans index d'arrivée, on prend tout depuis l'index de départ
var tbEssai:Array= new Array("Madeleine","Valérie","Sophie","Pierre","Anne","Denise","Bertrand"); var tbNouveau:Array=tbEssai.slice(1) trace(tbNouveau)
Valérie,Sophie,Pierre,Anne,Denise,Bertrand
Avec un index de départ négatif, on compte depuis la fin du tableau avec -1 pour le dernier élément. Ici Anne est en -3.
Avec un index d'arrivée négatif, pareil : on compte depuis la fin avec -1 pour le dernier élément.
par exemple Valérie,Sophie,Pierre mais en partant de la fin
var tbEssai:Array= new Array("Madeleine","Valérie","Sophie","Pierre","Anne","Denise","Bertrand"); // on veux Valérie,Sophie,Pierre // de Valérie (-6) à Anne Exclue (-3) var tbNouveau:Array=tbEssai.slice(-6,-3) trace(tbNouveau)
Valérie,Sophie,Pierre
sans paramètres
Là, je me permets d'attirer votre attention, si d'aventure ce long exposé un peu soporifique vous a engourdis, c'est le moment de vous secouer du neuronne
Quand on ne passe pas d'argument à slice on obtient une copie du tableau :
var tbA:Array= new Array(15,30,50,20); var tbB:Array= tbA.slice() trace("tbA : "+tbA+"\ntbB : "+tbB)
tbA : 15,30,50,20 tbB : 15,30,50,20
Oui, oh ! La belle affaire…
J'en entends maugréer qu'il n'y avait pas de quoi se réveiller pour si peu, d'autant qu'on aurait tout aussi bien pu écrire :
var tbB:Array= tbA;
Oui… Mais non.
Une chose importante à savoir en ce qui concerne les tableaux, c'est que les éléments y sont stockés par référence, et non par valeur.
Quand j'écris tbEssai[0]=2;
flashPlayer se souviendra, non pas de la valeur 2, mais de l'endroit où '2' a été écrit (en mémoire). Ce n'est pas la valeur de l'élément qui est mémorisée mais son adresse (référence).
En conséquence, regardons ce qui se passe avec la syntaxe tbA=tbB :
var tbA:Array=new Array(15,30,50,20); // On crée un nouveau tableau qui est le même que tbA var tbB:Array=tbA; trace("tbA : "+tbA+"\ntbB : "+tbB); //--> tbA : 15,30,50,20 //--> tbB : 15,30,50,20 // On modifie tbA[0] tbA[0]=700; trace("tbA : "+tbA+"\ntbB : "+tbB); //--> tbA : 700,30,50,20 //--> tbB : 700,30,50,20
Zut ! tbB[0] est lui aussi modifié !
Normal j'avais prévenu : par référence
tbB = tbA, ça implique que tbB stocke non pas les mêmes valeurs que tbA, mais les mêmes références que tbA. Il pointe sur les mêmes adresses mémoire…
Quand on écrit dans tbA[0], flashPlayer va écrire à l'adresse qu'il connait, la même que dans tbB[0]… Normal donc de lire la même chose depuis tbB[0] que depuis tbA[0]
D'où l'utilité de slice pour obtenir une copie : un tableau affichant les mêmes valeurs, mais stockées selon des références différentes…
Vérifions :
var tbA:Array=new Array(15,30,50,20); var tbB:Array=tbA.slice(); trace("tbA : "+tbA+"\ntbB : "+tbB); //--> tbA : 15,30,50,20 //--> tbB : 15,30,50,20 tbA[0]=700; trace("tbA : "+tbA+"\ntbB : "+tbB); //--> tbA : 700,30,50,20 //--> tbB : 15,30,50,20
Attention dans les fonctions
Donc, les tableaux stockent les éléments par référence.
Pour illustrer à quel point ce n'est pas un détail, je vous propose l'exercice suivant : écrire une fonction qui attend un tableau (d'int) et renvoie la valeur la plus grande - sans modifier le tableau en question.
On l'appellerait comme suit :
var tbA:Array=new Array(15,30,50,20); trace("tbA avant : "+tbA); trace(donneMax(tbA)); trace("tbA après : "+tbA);
Comme on est en plein dans le chapitre, vous êtes attentif à cette histoire de références et vous n'écrivez pas :
function donneMax(a:Array):int { a.sort(Array.DESCENDING); return a[0]; }
Sans quoi, voilà ce qui se serait passé :
tbA avant : 15,30,50,20 50 tbA après : 50,30,20,15
Vous avez pensé à faire une copie du tableau passé en paramètre
function donneMax(a:Array):int { // copie de travail :)) var tbCopie:Array=a.slice(); tbCopie.sort(Array.DESCENDING); return tbCopie[0]; }
Conclusion
Voilà, pour ce qui est du primordial de l'important de l'incontournable de ce qu'il est bon de savoir quant aux tableaux, vous êtes au point. J'ai tout dit (ou presque). Je me suis appliquée à ne pas utiliser les mêmes exemples que ceux de la doc, quand c'était possible, pour que vous ayez à disposition différentes illustrations du même point.
Je n'ai pas tout à fait tout dit en ce qui concerne indexOf et lastIndexOf, qui admettent un paramètre supplémentaire, et je n'ai pas précisé que la propriété length est en lecture/écriture… mais il faut bien que vous ayez le plaisir de découvrir des choses par vous même
Qui a dit mauvaise foi !?
D'accord, c'était surtout pour ne pas alourdir l'exposé suffisamment conséquent à mon goût. Et puis j'aime pas les bruits de ronflement, ça perturbe
En conséquence, et puisque vous avez survécu jusqu'ici, je vous invite, après une pause réparatrice, à faire connaissance avec 5 autres méthodes - espéciales AS3 - qui permettent de parcourir un tableau. Parcourir avec fonctions de rappel
Par ailleurs, uniquement pour FlashPlayer 10, nous disposons maintenant d'une classe Vector. Un vecteur est un tableau dont tous les éléments sont de même type. Les performances de cette classe sont peut-être meilleures que celles de Array, personne n'est d'accord et moi je ne me mouille pas
Vous trouverez un tutoriel sur le sujet, ici. Rendez vous directement à la conclusion pour trouver un lien vers des tests de performance.
Liens utiles
- Parcourir avec fonctions de rappel: forEach, some, every, filter, map
- D'autres types de boucles qui peuvent aussi être utiles pour programmer avec les tableaux
