web-dev-qa-db-fra.com

Objets vs tableaux en Javascript pour les paires clé / valeur

Supposons que vous ayez une structure de données très simple:

(personId, name)

... et vous souhaitez en stocker un certain nombre dans une variable javascript. Selon moi, vous avez trois options:

// a single object
var people = {
    1 : 'Joe',
    3 : 'Sam',
    8 : 'Eve'
};

// or, an array of objects
var people = [
    { id: 1, name: 'Joe'},
    { id: 3, name: 'Sam'},
    { id: 8, name: 'Eve'}
];

// or, a combination of the two
var people = {
    1 : { id: 1, name: 'Joe'},
    3 : { id: 3, name: 'Sam'},
    8 : { id: 8, name: 'Eve'}
};

La deuxième ou la troisième option est évidemment la voie à suivre si vous avez (ou vous attendez à ce que vous ayez) plus d'une "valeur" à stocker (par exemple, en ajoutant leur âge ou quelque chose), donc, pour les besoins de l'argument, supposons qu'il n'y aura jamais plus de valeurs de données nécessaires dans cette structure. Lequel choisissez-vous et pourquoi?


Edit: L'exemple montre maintenant la situation la plus courante: les identifiants non séquentiels.

78
nickf

Chaque solution a ses cas d'utilisation.

Je pense que la première solution est bonne si vous essayez de définir une relation un-à-un (comme un mappage simple), surtout si vous devez utiliser la clé comme clé de recherche.

La deuxième solution me semble la plus robuste en général, et je l'utiliserais probablement si je n'avais pas besoin d'une clé de recherche rapide:

  • Il est auto-descriptif, vous n'avez donc pas à dépendre de quiconque utilise personnes pour savoir que la clé est l'identifiant de l'utilisateur.
  • Chaque objet est fourni de manière autonome, ce qui est préférable pour transmettre les données ailleurs - au lieu de deux paramètres (id et nom), vous passez simplement autour des gens.
  • Il s'agit d'un problème rare, mais parfois les valeurs de clé peuvent ne pas être valides pour être utilisées comme clés. Par exemple, je voulais une fois mapper les conversions de chaînes (par exemple, ":" en ">"), mais comme ":" n'est pas un nom de variable valide, j'ai dû utiliser la deuxième méthode.
  • Il est facilement extensible, au cas où quelque part le long de la ligne, vous devriez ajouter plus de données à certains (ou à tous) les utilisateurs. (Désolé, je sais pour votre "pour le plaisir", mais c'est un aspect important.)

Le troisième serait bien si vous avez besoin d'un temps de recherche rapide + de certains des avantages énumérés ci-dessus (transmission des données, auto-description). Cependant, si vous n'avez pas besoin du temps de recherche rapide, c'est beaucoup plus lourd. De plus, dans tous les cas, vous courez le risque d'erreur si l'ID dans l'objet varie en quelque sorte de l'ID dans personnes.

57
Daniel Lew

En fait, il existe une quatrième option:

var people = ['Joe', 'Sam', 'Eve'];

car vos valeurs se trouvent être consécutives. (Bien sûr, vous devrez ajouter/soustraire un --- ou simplement mettre undefined comme premier élément).

Personnellement, j'irais avec votre (1) ou (3), car ce sera le plus rapide pour rechercher quelqu'un par ID (O logn au pire). Si vous devez trouver l'identifiant 3 dans (2), vous pouvez soit le rechercher par index (auquel cas mon (4) est correct), soit vous devez rechercher - O (n).

Clarification: je dis O (logn) est le pire qu'il puisse être car, AFAIK, et l'implémentation pourrait décider d'utiliser un arbre équilibré au lieu d'une table de hachage. Une table de hachage serait O (1), en supposant des collisions minimales.

Edit from nickf: J'ai depuis changé l'exemple dans l'OP, donc cette réponse peut ne plus avoir autant de sens. Excuses.

Posté

Ok, après l'édition, je choisirais l'option (3). Il est extensible (facile à ajouter de nouveaux attributs), propose des recherches rapides et peut également être itéré. Il vous permet également de passer de l'entrée à l'ID, si vous en avez besoin.

L'option (1) serait utile si (a) vous devez économiser de la mémoire; (b) vous n'avez jamais besoin de revenir de l'objet à l'id; (c) vous ne prolongerez jamais les données stockées (par exemple, vous ne pouvez pas ajouter le nom de famille de la personne)

L'option (2) est bonne si vous (a) devez conserver la commande; (b) besoin d'itérer tous les éléments; (c) n'a pas besoin de rechercher les éléments par id, sauf s'il est trié par id (vous pouvez faire une recherche binaire dans O (logn). Notez bien sûr que si vous devez le conserver, vous paierez un coût pour l'insertion.

7
derobert

En supposant que les données ne changeront jamais, la première option (objet unique) est la meilleure.

La simplicité de la structure signifie qu'elle est la plus rapide à analyser, et dans le cas de petits ensembles de données rarement (ou jamais) changeants tels que celui-ci, je ne peux qu'imaginer qu'elle sera fréquemment exécutée - auquel cas la surcharge minimale est la marche à suivre.

2
karim79

J'ai créé une petite bibliothèque pour gérer les paires de valeurs clés.

https://github.com/scaraveos/keyval.js#readme

Il utilise

  • un objet pour stocker les clés, ce qui permet des opérations rapides de suppression et de récupération de valeur et
  • une liste chaînée pour permettre une itération de valeur très rapide

J'espère que ça aide :)

2
scaraveos

La troisième option est la meilleure pour toute application prospective. Vous souhaiterez probablement ajouter plus de champs à votre enregistrement de personne, donc la première option ne convient pas. En outre, il est très probable que vous ayez un grand nombre de personnes à stocker et que vous souhaitiez rechercher des enregistrements rapidement - donc les jeter dans un tableau simple (comme cela est fait dans l'option # 2) n'est pas une bonne idée non plus.

Le troisième modèle vous donne la possibilité d'utiliser n'importe quelle chaîne comme ID, d'avoir des structures de personne complexes et d'obtenir et de définir des enregistrements de personne en un temps constant. C'est définitivement la voie à suivre.

Une chose qui manque à l'option # 3 est un ordre déterministe stable (qui est le côté positif de l'option # 2). Si vous en avez besoin, je recommanderais de conserver un tableau ordonné d'ID de personne en tant que structure distincte lorsque vous devez répertorier les personnes dans l'ordre. L'avantage est que vous pouvez conserver plusieurs tableaux de ce type, pour différents ordres du même ensemble de données.

1
levik

Étant donné votre contrainte que vous n'aurez que le nom comme valeur, je choisirais la première option. C'est le plus propre, a le moins de frais généraux et la recherche la plus rapide.

0
Nathaniel Reinhart