Les tableaux fournissent de nombreuses méthodes. Pour faciliter les choses, dans ce chapitre, ils sont divisés en groupes.
Nous connaissons déjà des méthodes qui ajoutent et suppriment des éléments depuis le début ou la fin :
arr.push(...items)
– ajoute des éléments à la fin,
arr.pop()
– extrait un élément de la fin,
arr.shift()
– extrait un élément depuis le début,
arr.unshift(...items)
– ajoute des éléments au début.
En voici quelques autres.
Comment supprimer un élément du tableau ?
Les tableaux sont des objets, nous pouvons donc essayer d'utiliser delete
:
let arr = ["Je", "aller", "à la maison"]; supprimer arr[1] ; // supprime "aller" alerte( arr[1] ); // non défini // maintenant arr = ["I", , "home"]; alert( arr.length ); // 3
L'élément a été supprimé, mais le tableau contient toujours 3 éléments, nous pouvons voir que arr.length == 3
.
C'est naturel, car delete obj.key
supprime une valeur par la key
. C'est tout ce qu'il fait. Très bien pour les objets. Mais pour les tableaux, nous souhaitons généralement que le reste des éléments se déplace et occupe la place libérée. Nous nous attendons à avoir un tableau plus court maintenant.
Des méthodes spéciales doivent donc être utilisées.
La méthode arr.splice est un couteau suisse pour les tableaux. Il sait tout faire : insérer, retirer et remplacer des éléments.
La syntaxe est :
arr.splice(start[, deleteCount, elem1, ..., elemN])
Il modifie arr
à partir de l'index start
: supprime les éléments deleteCount
puis insère elem1, ..., elemN
à leur place. Renvoie le tableau des éléments supprimés.
Cette méthode est facile à comprendre par des exemples.
Commençons par la suppression :
let arr = ["Je", "étudier", "JavaScript"]; arr.splice(1, 1); // de l'index 1 supprime 1 élément alerte( arr ); // ["Je", "JavaScript"]
Facile, non ? À partir de l’index 1
il a supprimé 1
élément.
Dans l'exemple suivant, nous supprimons 3 éléments et les remplaçons par les deux autres :
let arr = ["Je", "étudier", "JavaScript", "droit", "maintenant"]; // supprime les 3 premiers éléments et les remplace par un autre arr.splice(0, 3, "Allons", "danse"); alert( arr ) // maintenant ["Allons", "dansons", "à droite", "maintenant"]
Ici, nous pouvons voir que splice
renvoie le tableau des éléments supprimés :
let arr = ["Je", "étudier", "JavaScript", "droit", "maintenant"]; // supprime les 2 premiers éléments laissez supprimé = arr.splice(0, 2); alerte (supprimé); // "Je", "étude" <-- tableau d'éléments supprimés
La méthode splice
est également capable d'insérer les éléments sans aucun retrait. Pour cela, nous devons définir deleteCount
sur 0
:
let arr = ["Je", "étudier", "JavaScript"]; // à partir de l'index 2 // supprime 0 // puis insérez "complexe" et "langue" arr.splice(2, 0, "complexe", "langue"); alerte( arr ); // "Je", "étude", "complexe", "langage", "JavaScript"
Index négatifs autorisés
Ici et dans d'autres méthodes de tableau, les index négatifs sont autorisés. Ils précisent la position à partir de la fin du tableau, comme ici :
soit arr = [1, 2, 5]; // à partir de l'index -1 (à un pas de la fin) // supprime 0 élément, // puis insère 3 et 4 arr.splice(-1, 0, 3, 4); alerte( arr ); // 1,2,3,4,5
La méthode arr.slice est beaucoup plus simple que la arr.splice
d'apparence similaire.
La syntaxe est :
arr.slice([début], [fin])
Il renvoie un nouveau tableau en copiant tous les éléments du start
à end
de l'index (sans compter end
). start
et end
peuvent être négatifs, dans ce cas, la position à partir de la fin du tableau est supposée.
C'est similaire à une méthode de chaîne str.slice
, mais au lieu de sous-chaînes, elle crée des sous-tableaux.
Par exemple:
let arr = ["t", "e", "s", "t"]; alerte( arr.slice(1, 3) ); // e,s (copie de 1 à 3) alerte( arr.slice(-2) ); // s,t (copie de -2 jusqu'à la fin)
On peut aussi l'appeler sans arguments : arr.slice()
crée une copie de arr
. Ceci est souvent utilisé pour obtenir une copie pour des transformations ultérieures qui ne devraient pas affecter le tableau d'origine.
La méthode arr.concat crée un nouveau tableau qui inclut les valeurs d'autres tableaux et des éléments supplémentaires.
La syntaxe est :
arr.concat(arg1, arg2...)
Il accepte n'importe quel nombre d'arguments – soit des tableaux, soit des valeurs.
Le résultat est un nouveau tableau contenant les éléments de arr
, puis arg1
, arg2
etc.
Si un argument argN
est un tableau, alors tous ses éléments sont copiés. Sinon, l'argument lui-même est copié.
Par exemple:
soit arr = [1, 2]; // crée un tableau à partir de : arr et [3,4] alerte( arr.concat([3, 4]) ); // 1,2,3,4 // crée un tableau à partir de : arr et [3,4] et [5,6] alert( arr.concat([3, 4], [5, 6]) ); // 1,2,3,4,5,6 // crée un tableau à partir de : arr et [3,4], puis ajoute les valeurs 5 et 6 alert( arr.concat([3, 4], 5, 6) ); // 1,2,3,4,5,6
Normalement, il copie uniquement les éléments des tableaux. Les autres objets, même s'ils ressemblent à des tableaux, sont ajoutés dans leur ensemble :
soit arr = [1, 2]; laissez arrayLike = { 0 : "quelque chose", longueur : 1 } ; alert( arr.concat(arrayLike) ); // 1,2,[objet Objet]
…Mais si un objet de type tableau a une propriété spéciale Symbol.isConcatSpreadable
, alors il est traité comme un tableau par concat
: ses éléments sont ajoutés à la place :
soit arr = [1, 2]; laissez arrayLike = { 0 : "quelque chose", 1 : « autre », [Symbol.isConcatSpreadable] : vrai, longueur : 2 } ; alert( arr.concat(arrayLike) ); // 1,2,quelque chose,autre
La méthode arr.forEach permet d'exécuter une fonction pour chaque élément du tableau.
La syntaxe :
arr.forEach(fonction(élément, index, tableau) { // ... faire quelque chose avec un élément });
Par exemple, ceci montre chaque élément du tableau :
// pour chaque élément, alerte d'appel ["Bilbo", "Gandalf", "Nazgul"].forEach(alerte);
Et ce code est plus élaboré sur leurs positions dans le tableau cible :
["Bilbo", "Gandalf", "Nazgul"].forEach((élément, index, tableau) => { alert(`${item} est à l'index ${index} dans ${array}`); });
Le résultat de la fonction (si elle en renvoie) est rejeté et ignoré.
Voyons maintenant les méthodes qui effectuent une recherche dans un tableau.
Les méthodes arr.indexOf et arr.includes ont la syntaxe similaire et font essentiellement la même chose que leurs homologues de chaîne, mais opèrent sur des éléments au lieu de caractères :
arr.indexOf(item, from)
– recherche item
à partir de l'index from
et renvoie l'index où il a été trouvé, sinon -1
.
arr.includes(item, from)
– recherche item
à partir de l'index from
, renvoie true
s'il est trouvé.
Habituellement, ces méthodes sont utilisées avec un seul argument : l’ item
à rechercher. Par défaut, la recherche s'effectue depuis le début.
Par exemple:
soit arr = [1, 0, faux] ; alerte( arr.indexOf(0) ); // 1 alert( arr.indexOf(false) ); // 2 alert( arr.indexOf(null) ); // -1 alert( arr.includes(1) ); // vrai
Veuillez noter que indexOf
utilise l'égalité stricte ===
à des fins de comparaison. Donc, si nous recherchons false
, il trouve exactement false
et non le zéro.
Si nous voulons vérifier si item
existe dans le tableau et n'avons pas besoin de l'index, alors arr.includes
est préféré.
La méthode arr.lastIndexOf est la même que indexOf
, mais recherche de droite à gauche.
soit fruits = ['Pomme', 'Orange', 'Pomme'] alert( fruits.indexOf('Apple') ); // 0 (première pomme) alert( fruits.lastIndexOf('Apple') ); // 2 (dernière pomme)
La méthode includes
gère NaN
correctement
Une caractéristique mineure mais remarquable de includes
est qu'il gère correctement NaN
, contrairement à indexOf
:
const arr = [NaN] ; alert( arr.indexOf(NaN) ); // -1 (faux, devrait être 0) alert( arr.includes(NaN) );// true (correct)
En effet, includes
a été ajoutée à JavaScript beaucoup plus tard et utilise l'algorithme de comparaison le plus récent en interne.
Imaginez que nous ayons un ensemble d'objets. Comment trouver un objet avec une condition spécifique ?
Ici, la méthode arr.find(fn) est utile.
La syntaxe est :
let result = arr.find(function(item, index, array) { // si true est renvoyé, l'élément est renvoyé et l'itération est arrêtée // pour un scénario faux, renvoie un élément non défini });
La fonction est appelée pour les éléments du tableau, les uns après les autres :
item
est l'élément.
index
est son index.
array
est le tableau lui-même.
S'il renvoie true
, la recherche est arrêtée, l' item
est renvoyé. Si rien n'est trouvé, undefined
est renvoyé.
Par exemple, nous avons un tableau d'utilisateurs, chacun avec les champs id
et name
. Trouvons celui avec id == 1
:
laisser les utilisateurs = [ {identifiant : 1, nom : "Jean"}, {identifiant : 2, nom : "Pete"}, {identifiant : 3, nom : "Marie"} ]; let user = users.find(item => item.id == 1); alert(utilisateur.nom); // John
Dans la vraie vie, les tableaux d’objets sont monnaie courante, la méthode find
est donc très utile.
Notez que dans l'exemple que nous proposons de find
la fonction item => item.id == 1
avec un argument. C'est typique, les autres arguments de cette fonction sont rarement utilisés.
La méthode arr.findIndex a la même syntaxe mais renvoie l'index où l'élément a été trouvé au lieu de l'élément lui-même. La valeur -1
est renvoyée si rien n'est trouvé.
La méthode arr.findLastIndex est similaire à findIndex
, mais recherche de droite à gauche, similaire à lastIndexOf
.
Voici un exemple :
laisser les utilisateurs = [ {identifiant : 1, nom : "Jean"}, {identifiant : 2, nom : "Pete"}, {identifiant : 3, nom : "Marie"}, {identifiant : 4, nom : "John"} ]; // Trouver l'index du premier John alert(users.findIndex(user => user.name == 'John')); // 0 // Trouver l'index du dernier John alert(users.findLastIndex(user => user.name == 'John')); // 3
La méthode find
recherche un seul (premier) élément qui fait que la fonction renvoie true
.
S'il y en a plusieurs, nous pouvons utiliser arr.filter(fn).
La syntaxe est similaire à find
, mais filter
renvoie un tableau de tous les éléments correspondants :
let results = arr.filter(function(item, index, array) { // si l'élément vrai est poussé vers les résultats et que l'itération continue // renvoie un tableau vide si rien n'est trouvé });
Par exemple:
laisser les utilisateurs = [ {identifiant : 1, nom : "John"}, {identifiant : 2, nom : "Pete"}, {identifiant : 3, nom : "Marie"} ]; // renvoie le tableau des deux premiers utilisateurs let someUsers = users.filter(item => item.id < 3); alert(someUsers.length); // 2
Passons aux méthodes qui transforment et réorganisent un tableau.
La méthode arr.map est l’une des plus utiles et des plus souvent utilisées.
Il appelle la fonction pour chaque élément du tableau et renvoie le tableau des résultats.
La syntaxe est :
let result = arr.map(function(item, index, array) { // renvoie la nouvelle valeur au lieu de l'élément });
Par exemple, ici nous transformons chaque élément en sa longueur :
let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length); alerte (longueurs); //5,7,6
L'appel à arr.sort() trie le tableau sur place , modifiant l'ordre de ses éléments.
Il renvoie également le tableau trié, mais la valeur renvoyée est généralement ignorée, car arr
lui-même est modifié.
Par exemple:
soit arr = [ 1, 2, 15 ]; // la méthode réorganise le contenu de arr arr.sort(); alerte( arr ); // 1, 15, 2
Avez-vous remarqué quelque chose d'étrange dans le résultat ?
L'ordre est devenu 1, 15, 2
. Incorrect. Mais pourquoi ?
Les éléments sont triés sous forme de chaînes par défaut.
Littéralement, tous les éléments sont convertis en chaînes à des fins de comparaison. Pour les chaînes, l'ordre lexicographique est appliqué et bien "2" > "15"
.
Pour utiliser notre propre ordre de tri, nous devons fournir une fonction comme argument de arr.sort()
.
La fonction doit comparer deux valeurs arbitraires et renvoyer :
fonction comparer (a, b) { si (a > b) renvoie 1 ; // si la première valeur est supérieure à la seconde si (a == b) renvoie 0 ; // si les valeurs sont égales si (a < b) renvoie -1 ; // si la première valeur est inférieure à la seconde }
Par exemple, pour trier par nombres :
fonction compareNumeric(a, b) { si (a > b) renvoie 1 ; si (a == b) renvoie 0 ; si (a < b) renvoie -1 ; } soit arr = [ 1, 2, 15 ]; arr.sort(compareNumeric); alerte(arr); // 1, 2, 15
Maintenant, cela fonctionne comme prévu.
Mettons-nous de côté et réfléchissons à ce qui se passe. L' arr
peut être un tableau de n'importe quoi, n'est-ce pas ? Il peut contenir des nombres, des chaînes, des objets ou autre. Nous avons un ensemble de quelques articles . Pour le trier, nous avons besoin d’une fonction de tri qui sache comparer ses éléments. La valeur par défaut est un ordre de chaîne.
La méthode arr.sort(fn)
implémente un algorithme de tri générique. Nous n'avons pas besoin de nous soucier de son fonctionnement interne (un tri rapide optimisé ou Timsort la plupart du temps). Il parcourra le tableau, comparera ses éléments à l'aide de la fonction fournie et les réorganisera, tout ce dont nous avons besoin est de fournir le fn
qui effectue la comparaison.
D’ailleurs, si jamais on veut savoir quels éléments sont comparés – rien ne nous empêche de les alerter :
[1, -2, 15, 2, 0, 8].sort(fonction(a, b) { alerte( a + " <> " + b ); renvoyer a - b ; });
L'algorithme peut comparer un élément avec plusieurs autres au cours du processus, mais il essaie de faire le moins de comparaisons possible.
Une fonction de comparaison peut renvoyer n'importe quel nombre
En fait, une fonction de comparaison n’a besoin que de renvoyer un nombre positif pour dire « plus » et un nombre négatif pour dire « moins ».
Cela permet d'écrire des fonctions plus courtes :
soit arr = [ 1, 2, 15 ]; arr.sort(function(a, b) { return a - b; }); alerte(arr); // 1, 2, 15
Fonctions fléchées pour le meilleur
Vous vous souvenez des fonctions fléchées ? Nous pouvons les utiliser ici pour un tri plus soigné :
arr.sort( (a, b) => a - b );
Cela fonctionne exactement de la même manière que la version plus longue ci-dessus.
Utiliser localeCompare
pour les chaînes
Vous vous souvenez de l'algorithme de comparaison de chaînes ? Il compare les lettres par leurs codes par défaut.
Pour de nombreux alphabets, il est préférable d'utiliser la méthode str.localeCompare
pour trier correctement les lettres, telles que Ö
.
Par exemple, trions quelques pays en allemand :
soit country = ['Österreich', 'Andorre', 'Vietnam']; alert( country.sort( (a, b) => a > b ? 1 : -1) ); // Andorre, Vietnam, Österreich (faux) alert( country.sort( (a, b) => a.localeCompare(b) ) ); // Andorre,Österreich,Vietnam (correct !)
La méthode arr.reverse inverse l'ordre des éléments dans arr
.
Par exemple:
soit arr = [1, 2, 3, 4, 5]; arr.reverse(); alerte( arr ); //5,4,3,2,1
Il renvoie également le tableau arr
après l'inversion.
Voici la situation de la vraie vie. Nous écrivons une application de messagerie et la personne entre dans la liste des destinataires délimités par des virgules : John, Pete, Mary
. Mais pour nous, un tableau de noms serait bien plus confortable qu’une seule chaîne. Comment l'obtenir ?
La méthode str.split(delim) fait exactement cela. Il divise la chaîne en un tableau par le délimiteur donné delim
.
Dans l'exemple ci-dessous, nous séparons par une virgule suivie d'un espace :
laissez les noms = 'Bilbon, Gandalf, Nazgul' ; let arr = noms.split(', '); pour (laissez le nom de l'arr) { alert( `Un message à ${name}.` ); // Un message à Bilbo (et à d'autres noms) }
La méthode split
a un deuxième argument numérique facultatif – une limite sur la longueur du tableau. S'il est fourni, alors les éléments supplémentaires sont ignorés. En pratique, il est rarement utilisé :
let arr = 'Bilbo, Gandalf, Nazgul, Saruman'.split(', ', 2); alerte(arr); // Bilbon, Gandalf
Divisé en lettres
L'appel à split(s)
avec un s
vide diviserait la chaîne en un tableau de lettres :
let str = "test"; alert( str.split('') ); // test
L'appel arr.join(glue) fait l'inverse pour split
. Il crée une chaîne d'éléments arr
joints par glue
entre eux.
Par exemple:
let arr = ['Bilbo', 'Gandalf', 'Nazgul']; let str = arr.join(';'); // colle le tableau dans une chaîne en utilisant ; alerte( str ); // Bilbo;Gandalf;Nazgul
Lorsque nous devons parcourir un tableau, nous pouvons utiliser forEach
, for
ou for..of
.
Lorsque nous devons parcourir et renvoyer les données pour chaque élément, nous pouvons utiliser map
.
Les méthodes arr.reduce et arr.reduceRight appartiennent également à cette race, mais sont un peu plus complexes. Ils sont utilisés pour calculer une valeur unique basée sur le tableau.
La syntaxe est :
let value = arr.reduce(function(accumulateur, élément, index, tableau) { //... }, [initial]);
La fonction est appliquée à tous les éléments du tableau les uns après les autres et « continue » son résultat jusqu'à l'appel suivant.
Arguments :
accumulator
– est le résultat de l’appel de fonction précédent, est égal initial
la première fois (si initial
est fourni).
item
– est l’élément actuel du tableau.
index
– est sa position.
array
– est le tableau.
Au fur et à mesure que la fonction est appliquée, le résultat de l’appel de fonction précédent est transmis au suivant comme premier argument.
Ainsi, le premier argument est essentiellement l’accumulateur qui stocke le résultat combiné de toutes les exécutions précédentes. Et à la fin, cela devient le résultat d' reduce
.
Cela semble compliqué ?
La façon la plus simple de comprendre cela est de prendre l’exemple.
Ici, nous obtenons la somme d'un tableau sur une seule ligne :
soit arr = [1, 2, 3, 4, 5]; soit result = arr.reduce((sum, current) => sum + current, 0); alerte (résultat); // 15
La fonction passée à reduce
n'utilise que 2 arguments, c'est généralement suffisant.
Voyons les détails de ce qui se passe.
Lors de la première exécution, sum
est la valeur initial
(le dernier argument de reduce
), égale à 0
, et current
est le premier élément du tableau, égal à 1
. Le résultat de la fonction est donc 1
.
Lors de la deuxième exécution, sum = 1
, nous y ajoutons le deuxième élément du tableau ( 2
) et revenons.
Au 3ème passage, sum = 3
et on y ajoute un élément supplémentaire, et ainsi de suite…
Le flux de calcul :
Ou sous forme de tableau, où chaque ligne représente un appel de fonction sur l'élément suivant du tableau :
sum | current | résultat | |
---|---|---|---|
le premier appel | 0 | 1 | 1 |
le deuxième appel | 1 | 2 | 3 |
le troisième appel | 3 | 3 | 6 |
le quatrième appel | 6 | 4 | 10 |
le cinquième appel | 10 | 5 | 15 |
Ici, nous pouvons clairement voir comment le résultat de l’appel précédent devient le premier argument du suivant.
On peut également omettre la valeur initiale :
soit arr = [1, 2, 3, 4, 5]; // suppression de la valeur initiale de la réduction (non 0) soit result = arr.reduce((somme, courant) => somme + courant); alerte( résultat ); // 15
Le résultat est le même. En effet, s'il n'y a pas d'initiale, alors reduce
prend le premier élément du tableau comme valeur initiale et commence l'itération à partir du 2ème élément.
Le tableau de calcul est le même que ci-dessus, moins la première ligne.
Mais une telle utilisation requiert une extrême prudence. Si le tableau est vide, l'appel reduce
sans valeur initiale génère une erreur.
Voici un exemple :
soit arr = []; // Erreur : réduction d'un tableau vide sans valeur initiale // si la valeur initiale existait, la réduction la renverrait pour l'arr vide. arr.reduce((somme, courant) => somme + courant);
Il est donc conseillé de toujours préciser la valeur initiale.
La méthode arr.reduceRight fait la même chose mais va de droite à gauche.
Les tableaux ne forment pas un type de langage distinct. Ils sont basés sur des objets.
typeof
n'aide donc pas à distinguer un objet simple d'un tableau :
alerte (type de {}); // objet alerte (type de []); // objet (identique)
…Mais les tableaux sont si souvent utilisés qu'il existe une méthode spéciale pour cela : Array.isArray(value). Il renvoie true
si la value
est un tableau et false
dans le cas contraire.
alerte(Array.isArray({})); // FAUX alerte(Array.isArray([])); // vrai
Presque toutes les méthodes de tableau qui appellent des fonctions – comme find
, filter
, map
, à l'exception notable de sort
, acceptent un paramètre supplémentaire facultatif thisArg
.
Ce paramètre n'est pas expliqué dans les sections ci-dessus, car il est rarement utilisé. Mais pour être complet, nous devons le couvrir.
Voici la syntaxe complète de ces méthodes :
arr.find(func, thisArg); arr.filter(func, thisArg); arr.map(func, thisArg); //... // thisArg est le dernier argument facultatif
La valeur du paramètre thisArg
devient this
pour func
.
Par exemple, nous utilisons ici une méthode d'objet army
comme filtre, et thisArg
passe le contexte :
laissez l'armée = { Âge minimum: 18, Âge maximum : 27 ans, canJoin (utilisateur) { return user.age >= this.minAge && user.age < this.maxAge; } } ; laisser les utilisateurs = [ {âge : 16}, {âge : 20}, {âge : 23}, {âge : 30} ]; // recherche des utilisateurs pour qui army.canJoin renvoie true let soldats = users.filter(army.canJoin, army); alert(soldiers.length); // 2 alert(soldiers[0].age); // 20 alert(soldiers[1].age); // 23
Si dans l'exemple ci-dessus nous utilisions users.filter(army.canJoin)
, alors army.canJoin
serait appelé en tant que fonction autonome, avec this=undefined
, conduisant ainsi à une erreur instantanée.
Un appel à users.filter(army.canJoin, army)
peut être remplacé par users.filter(user => army.canJoin(user))
, qui fait la même chose. Ce dernier est utilisé plus souvent, car il est un peu plus facile à comprendre pour la plupart des gens.
Un aide-mémoire des méthodes de tableau :
Pour ajouter/supprimer des éléments :
push(...items)
– ajoute des éléments à la fin,
pop()
– extrait un élément de la fin,
shift()
– extrait un élément depuis le début,
unshift(...items)
– ajoute des éléments au début.
splice(pos, deleteCount, ...items)
– à l'index pos
supprime les éléments deleteCount
et insère items
.
slice(start, end)
– crée un nouveau tableau, y copie les éléments du start
à end
de l’index (non inclus).
concat(...items)
– renvoie un nouveau tableau : copie tous les membres du tableau actuel et y ajoute items
. Si l'un des items
est un tableau, alors ses éléments sont pris en compte.
Pour rechercher parmi les éléments :
indexOf/lastIndexOf(item, pos)
– recherche item
à partir de la position pos
et renvoie l'index ou -1
s'il n'est pas trouvé.
includes(value)
– renvoie true
si le tableau a value
, sinon false
.
find/filter(func)
– filtre les éléments via la fonction, renvoie la première/toutes les valeurs qui la font renvoyer true
.
findIndex
est comme find
, mais renvoie l'index au lieu d'une valeur.
Pour parcourir les éléments :
forEach(func)
– appelle func
pour chaque élément, ne renvoie rien.
Pour transformer le tableau :
map(func)
– crée un nouveau tableau à partir des résultats de l’appel func
pour chaque élément.
sort(func)
– trie le tableau sur place, puis le renvoie.
reverse()
– inverse le tableau sur place, puis le renvoie.
split/join
– convertit une chaîne en tableau et inversement.
reduce/reduceRight(func, initial)
– calcule une valeur unique sur le tableau en appelant func
pour chaque élément et en transmettant un résultat intermédiaire entre les appels.
En plus:
Array.isArray(value)
vérifie que value
est un tableau, si c'est le cas renvoie true
, sinon false
.
Veuillez noter que les méthodes sort
, reverse
et splice
modifient le tableau lui-même.
Ces méthodes sont les plus utilisées, elles couvrent 99% des cas d'usage. Mais il y en a quelques autres :
arr.some(fn)/arr.every(fn) vérifie le tableau.
La fonction fn
est appelée sur chaque élément du tableau de la même manière que map
. Si l’un ou tous les résultats sont true
, renvoie true
, sinon false
.
Ces méthodes se comportent un peu comme ||
et &&
: si fn
renvoie une valeur véridique, arr.some()
renvoie immédiatement true
et arrête d'itérer sur le reste des éléments ; si fn
renvoie une valeur fausse, arr.every()
renvoie immédiatement false
et arrête également d'itérer sur le reste des éléments.
Nous pouvons utiliser every
pour comparer des tableaux :
function arraysEqual(arr1, arr2) { return arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]); } alert( arraysEqual([1, 2], [1, 2])); // vrai
arr.fill(value, start, end) – remplit le tableau avec value
répétitive du start
à end
de l’index.
arr.copyWithin(target, start, end) – copie ses éléments de la position start
jusqu'à la position end
en lui-même , à la position target
(écrase l'existant).
arr.flat(profondeur)/arr.flatMap(fn) crée un nouveau tableau plat à partir d'un tableau multidimensionnel.
Pour la liste complète, consultez le manuel.
À première vue, il peut sembler qu’il existe de nombreuses méthodes, assez difficiles à retenir. Mais en réalité, c'est beaucoup plus simple.
Parcourez l’aide-mémoire juste pour en être conscient. Ensuite, résolvez les tâches de ce chapitre pour vous entraîner, afin d'avoir de l'expérience avec les méthodes de tableau.
Ensuite, chaque fois que vous avez besoin de faire quelque chose avec un tableau et que vous ne savez pas comment faire, venez ici, regardez l'aide-mémoire et trouvez la bonne méthode. Des exemples vous aideront à l’écrire correctement. Bientôt, vous mémoriserez automatiquement les méthodes, sans efforts particuliers de votre part.
importance : 5
Écrivez la fonction camelize(str)
qui change les mots séparés par des tirets comme « my-short-string » en « myShortString » en chameau.
C'est-à-dire : supprime tous les tirets, chaque mot après le tiret devient en majuscule.
Exemples :
camelize("background-color") == 'backgroundColor'; camelize("list-style-image") == 'listStyleImage'; camelize("-webkit-transition") == 'WebkitTransition';
Astuce PS : utilisez split
pour diviser la chaîne en un tableau, transformez-la et join
-la.
Ouvrez un bac à sable avec des tests.
fonction camelize(str) { retour str .split('-') // divise 'mon-long-mot' en tableau ['mon', 'long', 'mot'] .carte( // met en majuscule les premières lettres de tous les éléments du tableau sauf le premier // convertit ['my', 'long', 'word'] en ['my', 'Long', 'Word'] (mot, index) => index == 0 ? mot : mot[0].toUpperCase() + mot.slice(1) ) .rejoindre(''); // rejoint ['my', 'Long', 'Word'] dans 'myLongWord' }
Ouvrez la solution avec des tests dans un bac à sable.
importance : 4
Écrivez une fonction filterRange(arr, a, b)
qui obtient un tableau arr
, recherche les éléments avec des valeurs supérieures ou égales à a
et inférieures ou égales à b
et renvoie un résultat sous forme de tableau.
La fonction ne doit pas modifier le tableau. Il devrait renvoyer le nouveau tableau.
Par exemple:
soit arr = [5, 3, 8, 1]; laissez filtré = filterRange(arr, 1, 4); alerte (filtrée); // 3,1 (valeurs correspondantes) alerte( arr ); // 5,3,8,1 (non modifié)
Ouvrez un bac à sable avec des tests.
fonction filterRange(arr, a, b) { // ajout de crochets autour de l'expression pour une meilleure lisibilité return arr.filter(item => (a <= item && item <= b)); } soit arr = [5, 3, 8, 1]; laissez filtré = filterRange(arr, 1, 4); alerte (filtrée); // 3,1 (valeurs correspondantes) alerte( arr ); // 5,3,8,1 (non modifié)
Ouvrez la solution avec des tests dans un bac à sable.
importance : 4
Écrivez une fonction filterRangeInPlace(arr, a, b)
qui obtient un tableau arr
et en supprime toutes les valeurs sauf celles qui sont comprises entre a
et b
. Le test est : a ≤ arr[i] ≤ b
.
La fonction ne doit modifier que le tableau. Cela ne devrait rien retourner.
Par exemple:
soit arr = [5, 3, 8, 1]; filterRangeInPlace(arr, 1, 4); // supprimé les nombres sauf de 1 à 4 alerte( arr ); // [3, 1]
Ouvrez un bac à sable avec des tests.
fonction filterRangeInPlace (arr, a, b) { pour (soit i = 0; i < arr.length; i++) { soit val = arr[i]; // supprime si en dehors de l'intervalle si (val < a || val > b) { arr.splice(i, 1); je--; } } } soit arr = [5, 3, 8, 1]; filterRangeInPlace(arr, 1, 4); // supprimé les nombres sauf de 1 à 4 alerte( arr ); // [3, 1]
Ouvrez la solution avec des tests dans un bac à sable.
importance : 4
soit arr = [5, 2, 1, -10, 8]; // ... votre code pour le trier par ordre décroissant alerte( arr ); // 8, 5, 2, 1, -10
soit arr = [5, 2, 1, -10, 8]; arr.sort((a, b) => b - a); alerte( arr );
importance : 5
Nous avons un tableau de chaînes arr
. Nous aimerions en avoir une copie triée, mais gardez arr
inchangé.
Créez une fonction copySorted(arr)
qui renvoie une telle copie.
let arr = ["HTML", "JavaScript", "CSS"]; let sorted = copySorted(arr); alert( trié ); // CSS, HTML, JavaScript alerte( arr ); // HTML, JavaScript, CSS (aucun changement)
Nous pouvons utiliser slice()
pour faire une copie et exécuter le tri dessus :
fonction copySorted(arr) { return arr.slice().sort(); } let arr = ["HTML", "JavaScript", "CSS"]; let sorted = copySorted(arr); alert( trié ); alerte( arr );
importance : 5
Créez une fonction constructeur Calculator
qui crée des objets calculatrice « extensibles ».
La tâche se compose de deux parties.
Tout d'abord, implémentez la méthode calculate(str)
qui prend une chaîne comme "1 + 2"
au format "NUMBER Operator NUMBER" (délimité par des espaces) et renvoie le résultat. Doit comprendre plus +
et moins -
.
Exemple d'utilisation :
laissez calc = nouvelle calculatrice ; alerte( calc.calculate("3 + 7") ); // 10
Ajoutez ensuite la méthode addMethod(name, func)
qui apprend à la calculatrice une nouvelle opération. Il prend le name
de l'opérateur et la fonction à deux arguments func(a,b)
qui l'implémente.
Par exemple, ajoutons la multiplication *
, la division /
et la puissance **
:
soit powerCalc = nouvelle calculatrice ; powerCalc.addMethod("*", (a, b) => a * b); powerCalc.addMethod("/", (a, b) => a / b); powerCalc.addMethod("**", (a, b) => a ** b); soit result = powerCalc.calculate("2 ** 3"); alerte( résultat ); // 8
Pas de parenthèses ni d'expressions complexes dans cette tâche.
Les nombres et l'opérateur sont délimités par exactement un espace.
Il peut y avoir une gestion des erreurs si vous souhaitez l'ajouter.
Ouvrez un bac à sable avec des tests.
Veuillez noter comment les méthodes sont stockées. Ils sont simplement ajoutés à la propriété this.methods
.
Tous les tests et conversions numériques sont effectués dans la méthode calculate
. À l'avenir, il pourrait être étendu pour prendre en charge des expressions plus complexes.
fonction Calculatrice() { ceci.méthodes = { "-": (a, b) => a - b, "+": (a, b) => a + b } ; this.calculate = fonction (str) { laissez split = str.split(' '), une = +diviser[0], op = divisé[1], b = +diviser[2]; if (!this.methods[op] || isNaN(a) || isNaN(b)) { renvoyer NaN ; } renvoie this.methods[op](a, b); } ; this.addMethod = fonction (nom, fonction) { this.methods[nom] = func; } ; }
Ouvrez la solution avec des tests dans un bac à sable.
importance : 5
Vous disposez d'un tableau d'objets user
, chacun d'eux a user.name
. Écrivez le code qui le convertit en un tableau de noms.
Par exemple:
laissez john = { nom : "John", âge : 25 } ; laissez pete = { nom : "Pete", âge : 30 } ; laissez mary = { nom : "Marie", âge : 28 } ; laissez les utilisateurs = [ john, pete, mary ]; laissez noms = /* ... votre code */ alert( noms ); // Jean, Pete, Mary
laissez john = { nom : "John", âge : 25 } ; laissez pete = { nom : "Pete", âge : 30 } ; laissez mary = { nom : "Marie", âge : 28 } ; laissez les utilisateurs = [ john, pete, mary ]; let noms = utilisateurs.map(item => item.name); alert( noms ); // Jean, Pete, Mary
importance : 5
Vous disposez d’un tableau d’objets user
, chacun ayant name
, surname
et id
.
Écrivez le code pour créer un autre tableau à partir de celui-ci, d'objets avec id
et fullName
, où fullName
est généré à partir de name
et surname
.
Par exemple:
let john = { nom : "John", nom de famille : "Smith", identifiant : 1 } ; let pete = { nom : "Pete", nom de famille : "Hunt", identifiant : 2 } ; let mary = { nom : "Mary", nom de famille : "Clé", identifiant : 3 } ; laissez les utilisateurs = [ john, pete, mary ]; let usersMapped = /* ... votre code ... */ /* utilisateursMapped = [ { fullName : "John Smith", identifiant : 1 }, { fullName : "Pete Hunt", identifiant : 2 }, { nom complet : "Mary Key", identifiant : 3 } ] */ alerte (usersMaped[0].id ) // 1 alerte (usersMaped[0].fullName ) // John Smith
Donc, en réalité, vous devez mapper un tableau d’objets à un autre. Essayez d'utiliser =>
ici. Il y a un petit hic.
let john = { nom : "John", nom de famille : "Smith", identifiant : 1 } ; let pete = { nom : "Pete", nom de famille : "Hunt", identifiant : 2 } ; let mary = { nom : "Mary", nom de famille : "Clé", identifiant : 3 } ; laissez les utilisateurs = [ john, pete, mary ]; laissez usersMaped = users.map(user => ({ nom complet : `${user.name} ${user.surname}`, identifiant : utilisateur.id })); /* utilisateursMapped = [ { fullName : "John Smith", identifiant : 1 }, { fullName : "Pete Hunt", identifiant : 2 }, { nom complet : "Mary Key", identifiant : 3 } ] */ alert(usersMaped[0].id ); // 1 alert(usersMaped[0].fullName ); // John Smith
Veuillez noter que dans les fonctions fléchées, nous devons utiliser des parenthèses supplémentaires.
On ne peut pas écrire ainsi :
laissez usersMaped = users.map(user => { nom complet : `${user.name} ${user.surname}`, identifiant : utilisateur.id });
On s'en souvient, il existe deux fonctions fléchées : sans value => expr
et avec value => {...}
.
Ici, JavaScript traiterait {
comme le début du corps de la fonction, et non comme le début de l'objet. La solution consiste à les placer entre parenthèses « normales » :
laissez usersMaped = users.map(user => ({ nom complet : `${user.name} ${user.surname}`, identifiant : utilisateur.id }));
Maintenant, très bien.
importance : 5
Écrivez la fonction sortByAge(users)
qui obtient un tableau d'objets avec la propriété age
et les trie par age
.
Par exemple:
laissez john = { nom : "John", âge : 25 } ; laissez pete = { nom : "Pete", âge : 30 } ; laissez mary = { nom : "Marie", âge : 28 } ; laissez arr = [ pete, john, mary ]; sortByAge(arr); // maintenant : [john, mary, pete] alerte(arr[0].name); // John alerte(arr[1].name); // Marie alerte(arr[2].name); // Pierre
fonction sortByAge(arr) { arr.sort((a, b) => a.age - b.age); } laissez john = { nom : "John", âge : 25 } ; laissez pete = { nom : "Pete", âge : 30 } ; laissez mary = { nom : "Marie", âge : 28 } ; laissez arr = [ pete, john, mary ]; sortByAge(arr); // maintenant le tri est : [john, mary, pete] alerte(arr[0].name); // John alerte(arr[1].name); // Marie alerte(arr[2].name); // Pierre
importance : 3
Écrivez la fonction shuffle(array)
qui mélange (réorganise de manière aléatoire) les éléments du tableau.
Plusieurs cycles de shuffle
peuvent conduire à différents ordres d'éléments. Par exemple:
soit arr = [1, 2, 3]; mélanger (arr); //arr = [3, 2, 1] mélanger (arr); //arr = [2, 1, 3] mélanger (arr); //arr = [3, 1, 2] //...
Tous les ordres d'éléments doivent avoir une probabilité égale. Par exemple, [1,2,3]
peut être réorganisé comme [1,2,3]
ou [1,3,2]
ou [3,1,2]
etc, avec une probabilité égale pour chaque cas.
La solution simple pourrait être :
fonction shuffle (tableau) { array.sort(() => Math.random() - 0,5); } soit arr = [1, 2, 3]; mélanger (arr); alerte(arr);
Cela fonctionne un peu, car Math.random() - 0.5
est un nombre aléatoire qui peut être positif ou négatif, donc la fonction de tri réorganise les éléments de manière aléatoire.
Mais comme la fonction de tri n’est pas destinée à être utilisée de cette façon, toutes les permutations n’ont pas la même probabilité.
Par exemple, considérez le code ci-dessous. Il exécute shuffle
1 000 000 fois et compte les apparitions de tous les résultats possibles :
fonction shuffle (tableau) { array.sort(() => Math.random() - 0,5); } // décompte des apparitions pour toutes les permutations possibles laissez compter = { '123' : 0, '132' : 0, '213' : 0, '231' : 0, '321' : 0, '312' : 0 } ; pour (soit i = 0; i < 1000000; i++) { soit tableau = [1, 2, 3]; mélanger (tableau); count[array.join('')]++; } // affiche le nombre de toutes les permutations possibles pour (laisser la clé entrer le nombre) { alert(`${key} : ${count[key]}`); }
Un exemple de résultat (dépend du moteur JS) :
123 : 250706 132 : 124425 213 : 249618 231: 124880 312: 125148 321: 125223
Nous pouvons voir clairement le biais: 123
et 213
apparaissent beaucoup plus souvent que les autres.
Le résultat du code peut varier entre les moteurs JavaScript, mais nous pouvons déjà voir que l'approche n'est pas fiable.
Pourquoi ça ne fonctionne pas? D'une manière générale, sort
est une «boîte noire»: nous lançons un tableau et une fonction de comparaison et nous nous attendons à ce que le tableau soit trié. Mais en raison de l'aléatoire total de la comparaison, la boîte noire devient folle, et la façon dont elle devient folle dépend de la mise en œuvre du béton qui diffère entre les moteurs.
Il existe d'autres bonnes façons de faire la tâche. Par exemple, il y a un grand algorithme appelé Fisher-Yates Shuffle. L'idée est de parcourir le tableau dans l'ordre inverse et d'échanger chaque élément avec un élément aléatoire avant:
fonction shuffle (array) { for (Laisse i = array.length - 1; i> 0; i--) { Soit j = math.floor (math.random () * (i + 1)); // Index aléatoire de 0 à i // échange des éléments array [i] et array [j] // Nous utilisons la syntaxe "destructring affectation" pour y parvenir // Vous trouverez plus de détails sur cette syntaxe dans les chapitres ultérieurs // même peut être écrit comme: // Soit t = array [i]; array [i] = array [j]; Array [J] = T [array [i], array [j]] = [array [j], array [i]]; } }
Tessons-le de la même manière:
fonction shuffle (array) { for (Laisse i = array.length - 1; i> 0; i--) { Soit j = math.floor (math.random () * (i + 1)); [array [i], array [j]] = [array [j], array [i]]; } } // compte d'apparences pour toutes les permutations possibles Laissez compter = { '123': 0, '132': 0, '213': 0, '231': 0, '321': 0, '312': 0 } ; pour (soit i = 0; i <1000000; i ++) { Soit Array = [1, 2, 3]; remanier (tableau); compter [array.join ('')] ++; } // montre des comptes de toutes les permutations possibles pour (que la clé compte) { alert (`$ {key}: $ {count [key]}`); }
L'exemple de sortie:
123: 166693 132: 166647 213: 166628 231: 167517 312: 166199 321: 166316
Ça a l'air bien maintenant: toutes les permutations apparaissent avec la même probabilité.
De plus, en termes de performances, l'algorithme Fisher-Yates est bien meilleur, il n'y a pas de «tri» au-dessus.
importance : 4
Écrivez la fonction getAverageAge(users)
qui obtient un tableau d'objets avec age
de la propriété et renvoie l'âge moyen.
La formule pour la moyenne est (age1 + age2 + ... + ageN) / N
.
Par exemple:
Soit John = {nom: "John", âge: 25}; Soit Pete = {nom: "Pete", âge: 30}; Soit Mary = {Name: "Mary", âge: 29}; Soit Arr = [John, Pete, Mary]; alerte (getAverageage (ARR)); // (25 + 30 + 29) / 3 = 28
fonction getAverageage (utilisateurs) { return users.reduce ((prev, user) => prev + user.age, 0) / users.length; } Soit John = {nom: "John", âge: 25}; Soit Pete = {nom: "Pete", âge: 30}; Soit Mary = {Name: "Mary", âge: 29}; Soit Arr = [John, Pete, Mary]; alerte (getAverageage (ARR)); // 28
importance : 4
Soit arr
un tableau.
Créez une fonction unique(arr)
qui doit renvoyer un tableau avec des éléments uniques de arr
.
Par exemple:
fonction unique(arr) { /* votre code */ } Laissez les cordes = ["Hare", "Krishna", "Hare", "Krishna", "Krishna", "Krishna", "Lièvre", "Lièvre", ":-O" ]; alerte (unique (cordes)); // Lièvre, Krishna, :-O
Ouvrez un bac à sable avec des tests.
Promenez-vous les articles de tableau:
Pour chaque élément, nous vérifierons si le tableau résultant a déjà cet élément.
S'il en est ainsi, ignorez, sinon ajoutez aux résultats.
fonction unique(arr) { Soit le résultat = []; pour (let str de arr) { if (! result. y compris (str)) { result.push (str); } } renvoyer le résultat ; } Laissez les cordes = ["Hare", "Krishna", "Hare", "Krishna", "Krishna", "Krishna", "Lièvre", "Lièvre", ":-O" ]; alerte (unique (cordes)); // Lièvre, Krishna, :-O
Le code fonctionne, mais il y a un problème de performance potentiel.
Le résultat de la méthode result.includes(str)
parcourt le result
du tableau et compare chaque élément à str
pour trouver le match.
Donc, s'il y a 100
éléments de result
et que personne ne correspond str
, alors il promettra le result
entier et fera exactement 100
comparaisons. Et si result
est grand, comme 10000
, il y aurait 10000
comparaisons.
Ce n'est pas un problème par lui-même, car les moteurs JavaScript sont très rapides, donc Walk 10000
est une question de microsecondes.
Mais nous faisons un tel test pour chaque élément de arr
, dans la boucle for
.
Donc, si arr.length
est 10000
nous aurons quelque chose comme 10000*10000
= 100 millions de comparaisons. C'est beaucoup.
La solution est donc bonne pour les petits tableaux.
Plus loin dans la carte des chapitres et définirons, nous verrons comment l'optimiser.
Ouvrez la solution avec des tests dans un bac à sable.
importance : 4
Disons que nous avons reçu un tableau d'utilisateurs dans le formulaire {id:..., name:..., age:... }
.
Créez une fonction groupById(arr)
qui en crée un objet, avec id
comme clé, et les éléments du tableau comme valeurs.
Par exemple:
Laissez les utilisateurs = [ {id: 'John', nom: "John Smith", âge: 20}, {id: 'Ann', nom: "Ann Smith", âge: 24}, {id: 'Pete', nom: "Pete Peterson", âge: 31}, ]; Laissez USERBYID = GroupById (utilisateurs); / * // Après l'appel, nous devrions avoir: usersbyid = { John: {id: 'John', nom: "John Smith", âge: 20}, Ann: {id: 'Ann', nom: "Ann Smith", âge: 24}, Pete: {id: 'Pete', nom: "Pete Peterson", âge: 31}, } * /
Une telle fonction est vraiment pratique lorsque vous travaillez avec les données du serveur.
Dans cette tâche, nous supposons que id
est unique. Il peut n'y avoir pas deux éléments de tableau avec le même id
.
Veuillez utiliser la méthode Array .reduce
dans la solution.
Ouvrez un bac à sable avec des tests.
fonction groupbyid (array) { return array.reduce ((obj, valeur) => { obj [value.id] = valeur; retour obj; }, {}) }
Ouvrez la solution avec des tests dans un bac à sable.