Données Tableaux

Identification

Infoforall

8 - Utilisation de tableaux de données


Nous allons maintenant formaliser plusieurs choses vues sur les tableaux et voir comment ils sont implémentés dans différents langages.

Cette activité comporte beaucoup de parties déjà rencontrées dans les activités de programmation Python.

Documents de cours : open document ou pdf

Evaluation ✎ : questions 5-6-7-8.

1 - Tableaux

Nous avons vu que les tableaux étaient un ensemble de données de même type comportant un nombre fixe de cases définies à la création du tableau.

On dit ainsi souvent que ces tableaux sont statiques dans la mesure où, une fois créé, on ne peut plus modifier leurs nombres d'éléments (par contre, on peut changer le contenu individuel de ces éléments).

Voyons maintenant pourquoi.

Voyons une petit partie des adresses mémoires d'un ordinateur. Ici, on a

  • Derrière Ad : le numéro-adresse de la case mémoire (donnée en décimal pour simplifier, mais souvent on les récupère en hexadécimal)
  • En rouge : l'octet stocké dans la case mémoire, exprimé également en base 10. Mais gardez bien à l'esprit qu'il s'agit physiquement d'un ensemble de 8 bits.
Contenu de la mémoire
Un petit apercu de la mémoire

01° Que vaut l'octet stocké à l'adresse 213 ? Convertir ce nombre N10 en base 2 de façon à visualiser les 8 bits réellement stockés à cet endroit.

...CORRECTION...

On voit qu'on y a stocké un octet correspont à N = 18 10

On doit donc activer le bit de poids 16.

Il reste 18-16 = 2 à encoder. On active le bit de poids 2.

On a donc N = 0001 0010 2

02° Peut-on savoir ce qui est stocké en mémoire si on ne connait pas l'encodage qui a été utilisé ?

...CORRECTION...

Et non. On ne peut pas le savoir

Lorsqu'on accède à la lecture de la mémoire octet par octet, on ne peut pas savoir ce qui a réellement été stocké. On peut au mieux faire des suppositions sur la signification de cette suite d'octets.

Il pourra s'agir d'entier signé encodé sur 2 octets (type short int), de flottants encodés sur 4 octets (type simple precision), sur des caractères encodés sur un octet (type char). Ou d'addresses mémoires encodés sur 4 octets ... Bref, impossible de savoir, à moins de reconnaitre un motif dans les octets.

Structure d'un tableau

Un tableau est caractérisé par plusieurs choses :

  • Une adresse mémoire initiale
  • Le type de données encodées dans les cases
  • Le nombre de cases dans le tableau

Imaginons que notre tableau contienne des flottants simple précision (4 octets par float).

Le premier flottant stocké est donc encodé par la suite d'octets 45 200 21 75

Mémoire avec groupement de 4 octets
Un petit apercu de la mémoire groupé par 4 octets

Il faut donc connaitre l'adresse de départ et lire ensuite les octets en le regroupant par groupe de 4.

Que vaut ce premier flottant ?

Si on représente 45 200 21 75 en binaire, on obtient :

>>> f"{45:0>8b} {200:0>8b} {21:0>8b} {75:0>8b}" '00101101 11001000 00010101 01001011'

Si on analyse le regroupement 00101101 11001000 00010101 01001011

  • Bit de signe : 0 : nombre positif
  • Les 8 bits encodant l'exposant : 0101101 1
    • On en déduit que D = int('01011011',2) = 91
    • L'exposant vaut donc E = 91 - 127 = -36
  • Mantisse (avec rajout du 1, devant : 1,1001000 00010101 01001011
    • On voit qu'on active les bits correspondantes aux puissances -1, -4, -11, -13 et -15
    • Cela donne 1 + 2-1 + 2-4 + 2-11 + 2-13 + 2-15
    • Au final, la mantisse vaut 1.563140869140625
  • Le nombre flottant encodé est donc +1.563140869140625 x 2-36
  • Résultat final : N = + 2.2746693417730057 . 10-11

Voilà. Nous avons donné un sens au premier élément car :

  1. Nous connaissons l'adresse de départ
  2. Nous connaissons le type d'encodage utilisé pour placer les données en mémoire : float sur 4 octets.

Si nous cherchons les autres flottants encodés, il faudra donc également regrouper les octets par 4 et donner à chaque association un numéro d'index. Commençons par le numéro 0 :

Mémoire avec groupement de 4 octets
Les index correspondant aux groupements de 4 octets
Avantages et désavantages des tableaux

Nous pouvons maintenant comprendre l'avantage principal d'une structure de données de ce type : on peut accéder très facilement à n'importe quel élément du tableau pourvu qu'on connaisse son index.

L'adresse visée est en effet : Adresse de départ + index x taille d'une donnée en octets.

Exemple :

  • Tableau contenant des floats simple précision (4 octets par donnée)
  • Adresse initiale : 200
  • Adresse de l'index 0 : adresse = 200 + 0 * 4 = 200
  • Adresse de l'index 1 : adresse = 200 + 1 * 4 = 204
  • Adresse de l'index 2 : adresse = 200 + 2 * 4 = 208
  • ...

Vous avez maintenant l'explication de l'intérêt de prendre 0 comme numéro initial d'index !

Avantages

La lecture des éléments n'est donc pas séquentielle : on peut accéder à l'élement 7 sans avoir dû lire les éléments 0-1-2-3-4-5-6.

Le temps d'accès à un élément est constant : on accède aussi rapidement à l'élément 200 qu'à l'élement 0 et cela que le tableau contienne 100 ou 100 000 éléments !.

Par contre, il y a trois désavantages principaux :

Il faut que les élements soient tous de même nature (et occupent dans le même nombre d'octets en mémoire)

Il faut que les zones mémoires soient contiguës. Il faut donc reserver la zone intialement : la taille est à définir à la création de façon à connaitre la dernière adresse.

On ne peut pas intercaler un nouvelle élément. Imaginons qu'on possède 4 éléments 0-1-2-3. Si on veut placer un élément entre le 0 et le 1, on va devoir déplacer d'abord les éléments 3 vers 4, 2 vers 3, 1 vers 2 et enfin placer le nouvel élément en index 1.

03° Imaginons que notre tableau de floats simple précision possède 200 éléments. Quelle est l'adresse de l'élément d'index 100 ?

...CORRECTION...

Il suffit de calculer 200+4*100 = 600.

Nous verrons plus tard d'autres structures de données ayant d'autres avantages et d'autres inconvénients. Comme toujours, il faudra étudier le problème et choisir ensuite la structure la plus adaptée à sa résolution.

Pour l'instant, nous nous limiterons aux tableaux.

2 - Tableau avec Python

1 - Déclaration d'un tableau en Python

Les éléments délimitateurs sont les crochets. Chaque élément du tableau est séparé des autres par une virgule.

Exemple

>>> tableau = ['a', 'b', 'c'] >>> tableau ['a', 'b', 'c'] >>> type(tableau) <class 'list'>

On voit que les "tableaux" sont en python des objets de classe list.

2 - Nombre d'éléments stockés

On peut utiliser la fonction native len pour obtenir le nombre d'éléments (ici des caractères pour le premier cas et des floats pour le deuxième cas) stockés dans le tableau.

Exemple

>>> tableau = ['a', 'b', 'c'] >>> nbr = len(tableau) >>> nbr 3
>>> tableau = [12.45, 5.0, 17.9, 4.32] >>> nbr = len(tableau) >>> nbr 4

On remarquera bien que dans les deux cas, nous avons des types list : on ne trouve pas d'indication directe sur le type des données contenues dans le tableau.

La variable tableau désigne ici le conteneur, pas le contenu.

3 - Accès à l'un des éléments

Pour accéder à l'un des éléments en particuliers, on peut noter le nom de la variable suivi de crochets et y placer l'index du numéro voulu.

Exemple

>>> tableau = ['a', 'b', 'c'] >>> element_0 = tableau[0] >>> element_0 'a' >>> element_1 = tableau[1] >>> element_1 'b' >>> element_2 = tableau[2] >>> element_2 'c'

La correspondance index - élément donne ceci sur l'exemple

Index 0 1 2
Elément 'a' 'b' 'c'
4 - Lecture des éléments un à un (méthode classique)

On peut aussi lire les éléments un par un en utilisant une boucle FOR couplée à la fonction len pour connaitre la valeur limite à placer pour l'indice d'incrémentation de la boucle.

Ainsi avec

 t_notes_A = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] 

Nous avons 14 éléments avec un index 0-1-2-3-4-5-6-7-8-9-10-11-12-13.

Index 0 1 2 3 4 5 6 7 8 9 10 11 12 13
Elément 15 18 8 10 12 15 20 5 12 17 12 10 18 4

Il faudrait donc utiliser for index in range(14) :

Exemple

1 2 3 4 5
notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] nbr = len(notes) for index in range(nbr) : print(notes[index])

Ce programme va afficher ceci dans la console :

15 18 8 10 12 15 20 5 12 17 12 10 18 4

04° Un tableau référencé par la variable tableau possède 5 éléments. Donner les valeurs successives que va prendre la variable index si on utilise le code de la ligne 4.

4
for index in range(len(tableau)) :

...CORRECTION...

On aura successivement 0, 1, 2, 3 et 4.

5 - Lecture des éléments un à un (méthode nominative)

Cette gestion nominative d'itérer les éléments n'existe pas dans tous les langages.

1 2 3 4 5 6 7 8 9
notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] for element in notes : if element > 12 : print("Bien : ", element) elif element < 8 : print("Pas bien : ", element) else : print("Moyen : ", element)

Ce programme affiche "Bien", "Pas bien" ou "Moyen" devant chaque note sans avoir à passer par un index dans le code :

Bien : 15 Bien : 18 Moyen : 8 Moyen : 10 Moyen : 12 Bien : 15 Bien : 20 Pas bien : 5 Moyen : 12 Bien : 17 Moyen : 12 Moyen : 10 Bien : 18 Pas bien : 4

Quelle boucle for utiliser ?

Si vous devez modifier l'un des éléments : boucle for avec index.

Si vous devez différencier la gestion en fonction de la place de l'élément : boucle for avec index.

Si vous devez simplement lire les éléments : boucle for nominative.

6 - Mutabilité des tableaux dans Python

Dans la majorité des langages, les tableaux sont mutables : cela veut dire qu'on peut modifier les contenus d'un tableau après sa création. On dit qu'on peut modifier l'état du tableau.

En Python, le type list est mutable. Nous considérerons donc que les tableaux sont mutables lors de notre utilisation de Python.

>>> tableau = ['a', 'b', 'c'] >>> tableau ['a', 'b', 'c'] >>> tableau[0] = 'Z' >>> tableau ['Z', 'b', 'c']

Avantage (ou désavantage !) concret de mettre du contenu dans un tableau ? On peut modifier l'état du tableau (son contenu) depuis une fonction sans avoir besoin de mettre le mot clé global : le nom de la variable ne sert qu'à localiser l'adresse-mémoire menant à l'index.

Avant la modification :
Tableau mutable
Après la modification : tableau est toujours associé à Id12
Tableau mutable
7 - Effet de bord

En utilisant l'identifiant d'un tableau, on peut le modifier depuis l'intérieur d'une fonction sans avoir besoin de renvoyer le tableau.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
def multiplier(entree, coefficient) : '''PROCEDURE qui modifie le tableau entree en multipliant chaque valeur par le coefficient fourni :: param entree(list) :: un tableau ne contenant que des nombres entiers :: param coefficient(int) :: un entier servant de coefficient multiplicateur .. Effet de bord :: le paramètre entree est modifié par la procédure :: exemple :: >>> tab_test = [1,2,10] >>> multiplier(tab_test, 60) >>> tab_test [60, 120, 600] ''' for index in range(len(entree)) : entree[index] = entree[index] * coefficient if __name__ == '__main__' : import doctest doctest.testmod()

Comme vous pouvez le voir, pas de return : entree va contenir l'identifiant du tableau fourni lors de l'appel. On pourra ainsi aller modifier le vrai tableau directement en manipulant les index de la variable entree.

✎ 05° Créer la fonction compter qui possède un paramètre entree dans lequel on attend un tableau d'entiers. On compte dans cette fonction le nombre de notes supérieures à 10. On renvoie ce résultat.

Réfléxion : a-t-on vraiment besoin des index ?

  • Oui, boucle for numérique dans la fonction.
  • Non, boucle for nominative.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
def compter(entree) : '''Fonction qui renvoie le nombre d'éléments supérieurs à 10 dans le tableau entree :: param entree(list) :: un tableau ne contenant que des nombres entiers :: return(int) :: le nombre de notes supérieures à 10 .. Effet de bord :: Aucun : entree ne doit pas être modifié :: exemple :: >>> notes = [1,2,10,15,18] >>> nbr = compter(notes) >>> nbr 2 ''' pass if __name__ == '__main__' : import doctest doctest.testmod()

Fonction : il faudra un return.

✎ 06° Créer la procédure modifier qui attend en paramètre un tableau d'entiers. On remplace

  • les élements valant 10 ou plus par 20 et
  • les élements valant moins de 10 par 0.

S'agissant d'une procédure, on modifie donc le tableau par effet de bord.

Réfléxion : a-t-on vraiment besoin des index ?

  • Oui, boucle for numérique dans la fonction.
  • Non, boucle for nominative.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
def modifier(entree) : '''Procédure qui modifie les éléments du tableau entree par 0 ou 20 :: param entree(list) :: un tableau ne contenant que des nombres entiers :: return(None) :: procédure .. Effet de bord :: entree est modifiée :: exemple :: >>> notes = [1,2,10,15,18] >>> modifier(notes) >>> notes [0, 0, 20, 20, 20] ''' pass if __name__ == '__main__' : import doctest doctest.testmod()

Procédure : pas de return.

Point de détail : on notera qu'il ne s'agit pas réellement d'une procédure : Python ne sait gérer que des fonctions. Si on "oublie" le return, l'interpréteur va simplement créer une fonction qui renvoie None. On renvoie donc bien quelque chose enr réalité.

3 - Création d'un tableau en compréhension

Rappel

Déclaration de tableau par compréhension à partir d'un tableau initial

La déclaration d'un tableau par compréhension est celle qui consiste à formuler le contenu du tableau directement dans les crochets à l'aide d'une boucle for.

reponses = [None for valeur in entree]
>>> tab1 = [1, 2, 3] >>> sortie = [None for element in tab1] >>> sortie [None, None, None]

En réalité, on peut faire mieux que mettre None dans chaque case : on peut indiquer le calcul à faire directement !

Voilà pour créer une copie contenant exactement le double dans chaque case qu'un tableau initial :

reponses = [valeur * 2 for valeur in entree]
>>> tab1 = [1, 2, 3] >>> sortie = [element*2 for element in tab1] >>> sortie [2, 4, 6]

Si on veut l'intégrer dans une fonction :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
def doubler(entree) : '''Fonction qui renvoie un tableau où chaque élément est le double de l'élément correspondant du tableau entrée :: param entree(list) :: un tableau ne contenant que des nombres entiers :: return (list) :: le tableau où chaque élément est le double de l'élément du même index dans entree :: exemple :: >>> doubler([1,2,3,4]) [2, 4, 6, 8] ''' reponses = [valeur * 2 for valeur in entree] return reponses if __name__ == '__main__' : import doctest doctest.testmod() tableau_test = [10,-2,-3,-4] table_reponse = doubler(tableau_test)

C'est beaucoup plus simple à écrire qu'avec un for. En réalité, l'interpréteur Python réalise en arrière plan la boucle for.

Déclaration de tableau par compréhension avec un range

On peut également créer des tableaux contenant un nombre précis d'élements de façon assez facile : il suffit d'utliser range.

>>> tableau = [0 for valeur in range(10)] >>> tableau [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> tableau = [valeur*10 for valeur in range(10)] >>> tableau [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> import random >>> tableau = [random.randint(1,100) for valeur in range(10)] >>> tableau [42, 41, 96, 35, 58, 94, 16, 21, 84, 51]

✎ 07° Créer par compréhension un tableau de 20 éléments contenant de nombres aléatoires compris entre 20 et 50.

✎ 08° Créer par compréhension un tableau de 500 éléments contenant 0.

On peut même faire mieux : on peut inclure des tests ou des fonctions dans la construction.

Premier exemple : on crée un tableau de 50 éléments compris entre 0 et 20. On crée un second tableau à partir du premier : on ne garde que les nombres supérieurs ou égaux à 10.

>>> import random >>> tableau = [random.randint(0,20) for valeur in range(50)] >>> tableau_2 = [note for note in tableau if note >= 10] >>> tableau [12, 8, 1, 3, 3, 17, 8, 2, 2, 10, 15, 3, 16, 13, 5, 18, 12, 15, 19, 10, 9, 14, 0, 15, 11, 6, 11, 1, 10, 6, 17, 3, 17, 10, 9, 8, 1, 9, 7, 12, 15, 10, 15, 15, 9, 8, 18, 8, 9, 6] >>> tableau_2 [12, 17, 10, 15, 16, 13, 18, 12, 15, 19, 10, 14, 15, 11, 11, 10, 17, 17, 10, 12, 15, 10, 15, 15, 18]

On peut enfin utiliser des fonctions lors de la création. Imaginons qu'on dispose de cette fonction en mémoire :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
def pas_plus(valeur, seuil) : '''Fonction qui renvoie la valeur ou le seuil si la valeur est supérieure au seuil :: param valeur(int) :: l'entier à traiter :: param seuil(int) :: la valeur seuil maximale à renvoyer :: return (int) :: valeur ou seuil :: exemple :: >>> pas_plus(10,20) 10 >>> pas_plus(30,20) 20 ''' if valeur > seuil : return seuil return valeur if __name__ == '__main__' : import doctest doctest.testmod()
>>> import random >>> tableau = [pas_plus(random.randint(0,20), 15) for valeur in range(10)] >>> tableau [14, 15, 7, 14, 11, 1, 13, 12, 15, 1]

On obtient bien un tableau de 10 éléments sans qu'aucun élément ne soit plus grand que 15.

4 - Tracer des graphiques

Les tableaux peuvent servir à stocker diverses informations.

On trouve les tableaux dans quasiment tous les programmes traitant de données.

Nous allons voir ici un cas typique : le tracé de graphiques.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
# 1 - Importation des modules nécessaires import math import matplotlib.pyplot as plt # 2 - Constantes # 3 - Déclaration des fonctions def f(x) : '''Renvoie la valeur f(x) renvoyée par la fonction voulue pour x ::param x (int/float) :: un nombre ::return (int/float) :: f(x) ''' valeur = math.sqrt(x) return valeur # 4 - Programme principal # Création des tableaux de données valeurs_x = [ valeur/10 for valeur in range(1000) ] # Abscisse valeurs_y = [ f(x) for x in valeurs_x ] # Ordonnée xmax = max(valeurs_x ) ymax = max(valeurs_y ) # Création des courbes plt.plot(valeurs_x, valeurs_y, label="f(x)", color='orange') plt.xlabel("x") plt.ylabel("Racine de x") plt.title("Représentation de f(x)") plt.legend(loc='upper center') plt.axis([0, xmax, 0, ymax]) plt.grid() plt.show() # Affichage à l'écran des courbes

09° Tester ce programme pour vérifier qu'il affiche bien la courbe f(x) = √ x.

Représentation de la racine carrée

10° Que valent les valeurs minimale et maximale lorsqu'on utilise for valeur in range(1000) ?

...CORRECTION...

On part de 0 et on va jusqu'à 999. 1000 ne sera jamais atteint.

L'intervalle est bien [0;999]

11° Que valent les quatres premières valeurs et la valeur maximale du tableau lorsqu'on utilise la création par compréhension de la ligne 20 : valeurs_x = [ valeur/10 for valeur in range(1000) ] ?

...CORRECTION...

La valeur part en boucle de 0, 1, 2, 3 ... et on va jusqu'à 999. 1000 ne sera jamais atteint.

La liste contient donc des éléments valant 0, 0.1, 0.2, 0.3 jusqu'à 9.9

L'intervalle est bien [0.0;99.9]

12° Que valent les quatres premières valeurs de valeurs_y : valeurs_y = [ f(x) for x in valeurs_x ] ?

...CORRECTION...

La valeur part en boucle de 0, 1, 2, 3 ... et on va jusqu'à 999. 1000 ne sera jamais atteint.

La liste contient donc des éléments valant 0, 0.1, 0.2, 0.3 jusqu'à 9.9

L'intervalle est bien [0.0;99.9]

13° Que va renvoyer la fonction native max aux lignes 23 et 24 ?

...CORRECTION...

En ligne 23 : xmax contiendra 99.9

En ligne 24 : ymax contiendra la racine carré de 99.9

Quelques explications sur les dernières lignes :

27 28 29 30 31 32 33 34
plt.plot(valeurs_x, valeurs_y, label="f(x)", color='orange') plt.xlabel("x") plt.ylabel("Racine de x") plt.title("Représentation de f(x)") plt.legend(loc='upper center') plt.axis([0, xmax, 0, ymax]) plt.grid() plt.show() # Affichage à l'écran des courbes
  • L27 : Création de la courbe en fournissant la liste des abscisses, la liste des ordonnées, un label et une couleur
  • L28 : Légende sur l'axe X
  • L29 : Légende sur l'axe Y
  • L30 : Titre du graphiqe
  • L31 : Position des légendes
  • L32 : Liste des valeurs minimales et maximales sur les axes sous forme d'une liste : [Xmin, Xmax, Ymin, Ymax]
  • L33 : On affiche la grille à l'écran
  • L34 : On affiche la ou les courbes

Dernier exemple : on trace les représentations de racine carré de x, x et x carré sur l'intervalle [0;2[.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
# 1 - Importation des modules nécessaires import math import matplotlib.pyplot as plt # 2 - Constantes # 3 - Déclaration des fonctions # 4 - Programme principal # Création des tableaux de données valeurs_x = [ valeur/1000 for valeur in range(2000) ] # Abscisse valeurs_y1 = [ math.sqrt(x) for x in valeurs_x ] # Ordonnée valeurs_y2 = [ x for x in valeurs_x ] # Ordonnée valeurs_y3 = [ x**2 for x in valeurs_x ] # Ordonnée xmax = max(valeurs_x ) ymax = max(valeurs_y3 ) # Création des courbes plt.plot(valeurs_x, valeurs_y1, label="f(x)", color='orange') plt.plot(valeurs_x, valeurs_y2, label="g(x)", color='red') plt.plot(valeurs_x, valeurs_y3, label="h(x)", color='green') plt.xlabel("x") plt.ylabel("Valeurs en ordonnée") plt.title("Représentation des fonctions") plt.legend(loc='upper center') plt.axis([0, xmax, 0, ymax]) plt.grid() plt.show() # Affichage à l'écran des courbes
Représentation des trois fonctions

5 - Tableau dans Javascript

Si vous voulez tester les codes présentés dans votre navigateur, il suffit de créer un fichier HTML ne comportant qu'une balise <script> et </script> et d'y placer le code Javascript fourni.

1 - Déclaration d'un tableau en Javascript

Les éléments délimitateurs sont les crochets. Chaque élément du tableau est séparé des autres par une virgule.

Exemple

1 2 3
var tableau = ['a', 'b', 'c']; console.log(tableau); console.log(typeof tableau);

Ce code affiche ceci dans la console Web

Array(3) [ "a", "b", "c" ] object

On voit que les tableaux sont en javascript des objets de classe Array (array voulant dire tableau en anglais).

2 - Nombre d'éléments stockés

On peut utiliser l'attribut length pour obtenir le nombre d'éléments (ici des caractères pour le premier cas et des floats pour le deuxième cas) stockés dans le tableau.

Exemple

var tableau = ['a', 'b', 'c']; var nbr = tableau.length; console.log(nbr);

Dans la console Web, on obtient ceci :

3

La variable tableau désigne ici le conteneur, pas le contenu.

3 - Accès à l'un des éléments

Pour accéder à l'un des éléments en particuliers, on peut noter le nom de la variable suivi de crochets et y placer l'index du numéro voulu.

Exemple

var tableau = ['a', 'b', 'c']; var element_0 = tableau[0]; console.log(element_0); var element_1 = tableau[1]; console.log(element_1); var element_2 = tableau[2]; console.log(element_2);

Dans la console, l'affichage obtenu est :

a b c

La correspondance index - élément donne ceci sur l'exemple

Index 0 1 2
Elément 'a' 'b' 'c'
4 - Lecture des éléments un à un (méthode classique)

On peut aussi lire les éléments un par un en utilisant une boucle FOR couplée à length pour connaitre la valeur limite à placer pour l'indice d'incrémentation de la boucle.

Ainsi avec

var t_notes_A = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] 

Nous avons 14 éléments avec un index 0-1-2-3-4-5-6-7-8-9-10-11-12-13.

Index 0 1 2 3 4 5 6 7 8 9 10 11 12 13
Elément 15 18 8 10 12 15 20 5 12 17 12 10 18 4
1 2 3 4
var notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] for (var index = 0; index < notes.length; index=index+1) { console.log(notes[index]); }

Ce programme va afficher ceci dans la console Web :

15 18 8 10 12 15 20 5 12 17 12 10 18 4
5 - Lecture des éléments un à un (méthode nominative)

Cette gestion nominative d'itérer les éléments n'existe pas dans tous les langages.

1 2 3 4
var notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] for (var element of notes) { console.log(element); }

Ce programme affiche la même chose que le précédent. On notera la présence d'un for of là où Python possède un for in.

Ce programme va afficher ceci dans la console Web :

15 18 8 10 12 15 20 5 12 17 12 10 18 4

Quelle boucle for utiliser ?

Si vous devez modifier l'un des éléments : boucle for avec index.

Si vous devez différencier la gestion en fonction de la place de l'élément : boucle for avec index.

Si vous devez simplement lire les éléments : boucle for nominative.

6 - Mutabilité des tableaux dans Javascript

Dans la majorité des langages, les tableaux sont mutables : cela veut dire qu'on peut modifier les contenus d'un tableau après sa création. On dit qu'on peut modifier l'état du tableau.

En Javascript, le type list est mutable. Nous considérerons donc que les tableaux sont mutables lors de notre utilisation de Python.

var tableau = ['a', 'b', 'c']; tableau[0] = 'Z'; console.log(tableau);

Affichage dans la console :

Array(3) [ "Z", "b", "c" ]
7 - Effet de bord

Comme en python, en utilisant l'identifiant d'un tableau, on peut le modifier depuis l'intérieur d'une fonction sans avoir besoin de renvoyer le tableau.

En effet, la variable du tableau ne contient en réalité que l'adresse ou l'identifiant du tableau. Le paramètre de la fonction reçoit donc bien la vraie adresse et peut donc modifier le vrai tableau.

1 2 3 4 5 6 7 8 9 10 11 12 13 14
function multiplier(entree, coefficient) { /*PROCEDURE qui modifie le tableau entree en multipliant chaque valeur par le coefficient fourni :: param entree(array) :: un tableau ne contenant que des nombres entiers :: param coefficient(number) :: un nombre servant de coefficient multiplicateur .. Effet de bord :: le paramètre entree est modifié par la procédure */ for (var index = 0; index < entree.length; index=index+1) { entree[index] = entree[index] * coefficient; } } var test = [1,2,3]; multiplier(test,10); console.log(test);

Dans la console Web, on obtient alors ceci :

Array(3) [ 10, 20, 30 ]

Comme vous pouvez le voir, pas de return : entree va contenir l'identifiant du tableau fourni lors de l'appel. On pourra ainsi aller modifier le vrai tableau directement en manipulant les index de la variable entree.

6 - Création par extension avec append

La création d'un tableau par extension consiste à rajouter des éléments les uns après les autres. Il s'agit donc d'une création progressive.

Cette partie ne fait pas partie des attendus de la 1er NSI.

Néanmoins, la création progressive d'une liste est indispensable dans pas mal de situation. Cette notion sera de toutes manières vue en Terminale.

Nous avons déjà expliqué de nombreuses fois que les objets de classe list de Python ne sont pas vraiment des tableaux statiques.

Nous allons vous montrer ici qu'on peut rajouter des éléments à la fin d'un tableau de façon à augmenter son contenu. En 1er, nous n'utiliserons cette méthode que lors de la création, de façon à simuler le comportement d'un tableau statique classique.

Un exemple :

>>> a = [1,2,3] >>> a [1, 2, 3] >>> a.append(12) >>> a [1, 2, 3, 12]

On remarque bien que nous n'avons pas réalisé d'affectation : nous avons juste pris l'adresse du tableau (stocké dans a et utilisé la méthode append).

Il ne faut surtout pas écrire ceci :

>>> a = [1,2,3] >>> a = a.append(12) >>> a

14° Pourquoi ne faut-il par écrire a = a.append(12) à votre avis ?

...CORRECTION...

La méthode renvoie None. Le tableau est modifié par effet de bord.

Si vous utilisez le a = a.append(12), c'est donc comme si vous aviez noté a = None. C'est dommage : vous remplaçez la variable-tableau a par une variable-None.

De la même façon, append ne permet pas de rajouter les éléments d'un tableau à votre tableau : vous n'allez faire que rajouter le tableau entier en tant que tableau...

>>> b = [7,8,9] >>> a.append(b) >>> a [1, 2, 3, 12, [7, 8, 9]]

Maintenant que nous avons vu les deux principaux pièges de l'utilisation de append, voyons commment l'utiliser proprement pour créer un tableau.

  1. On crée un tableau vide. Par exemple : tableau = []
  2. On génère une boucle : for index in range(10) :
  3. Dans cette boucle, on ajoute les éléments au fur et à mesure :

A titre d'exemple, voici le code permettant de générer un tableau contenant une suite d'entiers de 0 jusqu'à 90, de 10 en 10.

On notera qu'on peut faire exactement la même chose avec une création par compréhension.

1 2 3 4
tableau = [] for index in range(10) : tableau[index].append(index*10)

15° Utiliser le code ci-dessous pour visualiser la création progressive du tableau. Lors de chaque passage en boucle, on rajoute un élément.

1 2 3 4 5
tableau = [] for index in range(10) : tableau[index].append(index*10) print(tableau)

...CORRECTION...

[0] [0, 10] [0, 10, 20] [0, 10, 20, 30] [0, 10, 20, 30, 40] [0, 10, 20, 30, 40, 50] [0, 10, 20, 30, 40, 50, 60] [0, 10, 20, 30, 40, 50, 60, 70] [0, 10, 20, 30, 40, 50, 60, 70, 80] [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

7 - FAQ

J'ai vu qu'il y avait aussi un for in en Javascript !

C'est vrai. Mais il ne fonctionne pas comme cela de Python.

L'équivalence est bien for in Python équivalent au for of Javascript.

Voici l'effet d'un for in sur un tableau Array en javascript :

1 2 3 4
var notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] for (var element in notes) { console.log(element); }

Ce programme va afficher ceci dans la console Web :

0 1 2 3 4 5 6 7 8 9 10 11 12 13

La variable element contient donc en réalité l'index du tableau.

Activité publiée le 26 01 2020
Dernière modification : 27 01 2020
Auteur : ows. h.