177 votes

Tableau vs. Objet efficacité en JavaScript

J'ai un modèle avec potentiellement des milliers d'objets. Je me demandais quelle serait la manière la plus efficace de les stocker et de récupérer un seul objet une fois que j'ai son identifiant. Les identifiants sont de longs nombres.

Alors voici les 2 options auxquelles je pensais. dans la première option, c'est un simple tableau avec un index croissant. dans la deuxième option, c'est un tableau associatif et peut-être un objet, si ça fait une différence. Ma question est laquelle est la plus efficace, lorsque j'ai principalement besoin de récupérer un seul objet, mais parfois aussi de les parcourir et de les trier.

Option une avec tableau non associatif :

var a = [{id: 29938, name: 'name1'},
         {id: 32994, name: 'name1'}];
function getObject(id) {
    for (var i=0; i < a.length; i++) {
        if (a[i].id == id) 
            return a[i];
    }
}

Option deux avec tableau associatif :

var a = [];  // peut-être que {} fait une différence ?
a[29938] = {id: 29938, name: 'name1'};
a[32994] = {id: 32994, name: 'name1'};
function getObject(id) {
    return a[id];
}

Mise à jour :

D'accord, je comprends qu'utiliser un tableau dans la deuxième option est hors de question. Donc la ligne de déclaration dans la deuxième option devrait vraiment être : var a = {}; et la seule question est : quel est le plus performant pour récupérer un objet avec un identifiant donné : un tableau ou un objet où l'identifiant est la clé.

et aussi, la réponse changera-t-elle si je dois trier la liste plusieurs fois ?

1 votes

Cela peut aider peut-être:: stackoverflow.com/questions/13309464/…

0 votes

Avez-vous besoin d'une collection triée en tout temps ? Si oui, il n'y a pas d'autre option qu'un tableau (bien que vous n'utilisiez pas les index comme vous le faites actuellement).

0 votes

@Jon en fait, si. Que voulez-vous dire par "comme vous le faites actuellement"?

173voto

Alp Points 10727

La version courte: Les tableaux sont généralement plus rapides que les objets. Mais il n'y a pas de solution 100% correcte.

Mise à jour 2017 - Test et résultats

var a1 = [{id: 29938, name: 'name1'}, {id: 32994, name: 'name1'}];

var a2 = [];
a2[29938] = {id: 29938, name: 'name1'};
a2[32994] = {id: 32994, name: 'name1'};

var o = {};
o['29938'] = {id: 29938, name: 'name1'};
o['32994'] = {id: 32994, name: 'name1'};

for (var f = 0; f < 2000; f++) {
    var newNo = Math.floor(Math.random()*60000+10000);
    if (!o[newNo.toString()]) o[newNo.toString()] = {id: newNo, name: 'test'};
    if (!a2[newNo]) a2[newNo] = {id: newNo, name: 'test' };
    a1.push({id: newNo, name: 'test'});
}

configuration de test résultats du test

Publication originale - Explication

Il y a des idées fausses dans votre question.

Il n'y a pas de tableaux associatifs en Javascript. Seulement des tableaux et des objets.

Voici des tableaux:

var a1 = [1, 2, 3];
var a2 = ["a", "b", "c"];
var a3 = [];
a3[0] = "a";
a3[1] = "b";
a3[2] = "c";

Celui-ci est aussi un tableau:

var a3 = [];
a3[29938] = "a";
a3[32994] = "b";

C'est essentiellement un tableau avec des trous dedans, car chaque tableau a un indexage continu. C'est plus lent que les tableaux sans trous. Mais itérer manuellement à travers le tableau est encore plus lent (souvent).

Voici un objet:

var a3 = {};
a3[29938] = "a";
a3[32994] = "b";

Voici un test de performance de trois possibilités:

Test de performance de recherche de tableau vs tableau troué vs objet

Une excellente lecture sur ces sujets chez Smashing Magazine: Écriture de JavaScript rapide et efficace en mémoire

0 votes

Dans votre test, il me dit que Holey Array est le plus rapide (120K contre 92K pour l'objet). Est-ce que cela a du sens?

0 votes

@Moshe Cela dépend beaucoup du navigateur. Consultez la comparaison des navigateurs en bas de la page.

1 votes

@Moshe Et donc toute discussion sur les performances en Javascript devrait être faite. :P

29voto

deceze Points 200115

Il ne s'agit pas vraiment d'une question de performances, car les tableaux et les objets fonctionnent très différemment (ou du moins ils sont censés le faire). Les tableaux ont un index continu 0..n, tandis que les objets associent des clés arbitraires à des valeurs arbitraires. Si vous voulez fournir des clés spécifiques, la seule option est un objet. Si vous ne vous souciez pas des clés, c'est un tableau.

Si vous essayez de définir des clés arbitraires (numériques) sur un tableau, vous subirez réellement une perte de performances, car fonctionnellement le tableau remplira tous les index intermédiaires :

> foo = [];
  []
> foo[100] = 'a';
  "a"
> foo
  [undefined, undefined, undefined, ..., "a"]

(Notez que le tableau ne contient pas <em>réellement</em> 99 valeurs <code>undefined</code>, mais il se comportera de cette manière puisque vous êtes censé <em>itérer</em> sur le tableau à un moment donné.)

Les littéraux pour les deux options devraient rendre très clair comment ils peuvent être utilisés :

var arr = ['foo', 'bar', 'baz'];     // pas de clés, même pas l'option pour cela
var obj = { foo : 'bar', baz : 42 }; // associatif par nature

0 votes

Je ne veux pas fournir de clés spécifiques. Je veux savoir ce qui fonctionne le mieux et je travaillerai avec cela. D'accord, donc dans la deuxième option, un tableau est hors de question. Mais que dire d'un objet par rapport à tableau non associatif ?

1 votes

@Moshe Il n'existe pas de tableau non associatif en Javascript. Si vous avez besoin de clés (nombres ou chaînes de caractères), utilisez un objet. Si vous avez juste besoin d'une liste (ordonnée), utilisez des tableaux. Point final. Les performances n'entrent pas en discussion. Si les performances sont cruciales et que vous pourriez vous passer de vos clés de toute manière, essayez celle qui fonctionne le mieux pour vous.

6 votes

Mais je veux savoir ce qui fonctionne le mieux : récupérer un objet à partir d'un tableau (en le parcourant) ou à partir d'un objet "associatif" où l'identifiant est la clé. Je suis désolé si ma question n'était pas claire...

14voto

sandstrom Points 2420

Avec ES6, la manière la plus performante serait d'utiliser une Map.

var myMap = new Map();

myMap.set(1, 'myVal');
myMap.set(2, { catName: 'Meow', age: 3 });

myMap.get(1);
myMap.get(2);

Vous pouvez utiliser les fonctionnalités ES6 dès aujourd'hui en utilisant un shim (https://github.com/es-shims/es6-shim).

Les performances varieront en fonction du navigateur et du scénario. Voici un exemple où Map est le plus performant : https://jsperf.com/es6-map-vs-object-properties/2


RÉFÉRENCE https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map

12 votes

Avez-vous des ressources pour étayer cela? D'après mes observations jusqu'à présent, les ensembles ES6 sont plus rapides que les tableaux, mais les cartes ES6 sont plus lentes que les objets et les tableaux.

1 votes

C'est plus "sémantique", pas plus performant, c'était la question.

5 votes

@AlexG je suis sûr que le titre indique clairement efficacité.

10voto

Paweł Points 1434

Dans NodeJS, si vous connaissez l'ID, la boucle à travers le tableau est très lente comparé à object[ID].

const uniqueString = require('unique-string');
const obj = {};
const arr = [];
var seeking;

//créer des données
for(var i=0;i<1000000;i++){
  var getUnique = `${uniqueString()}`;
  if(i===888555) seeking = getUnique;
  arr.push(getUnique);
  obj[getUnique] = true;
}

//récupérer l'élément du tableau
console.time('arrTimer');
for(var x=0;x

`Et les résultats :

Résultat du tableau :
arrTimer: 12.857ms
Résultat de l'objet :
objTimer: 0.051ms

Même si l'ID recherché est le premier dans le tableau/objet :

Résultat du tableau :
arrTimer: 2.975ms
Résultat de l'objet :
objTimer: 0.068ms`

7voto

Davem M Points 121

J'ai essayé d'amener cela au niveau suivant, littéralement.

Étant donné un tableau à 2 dimensions, dans lequel les axes x et y ont toujours la même longueur, est-il plus rapide de :

a) rechercher la cellule en créant un tableau à deux dimensions et en recherchant le premier index, suivi du deuxième index, c'est-à-dire :

var arr=[][]    
var cell=[x][y]    

ou

b) créer un objet avec une représentation sous forme de chaîne des coordonnées x et y, puis effectuer une seule recherche sur cet objet, c'est-à-dire :

var obj={}    
var cell = obj['x,y']    

Résultat :
Il s'avère qu'il est beaucoup plus rapide de faire deux recherches d'index numériques dans les tableaux que d'en faire une dans l'objet.

Résultats ici :

http://jsperf.com/arr-vs-obj-lookup-2

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X