web-dev-qa-db-fra.com

Comment garder un objet / tableau Javascript ordonné tout en conservant les recherches de clés?

J'ai quelques données que j'ai initialement stockées dans un objet Javascript générique, avec l'ID comme clé:

{
  "7": {"id":"7","name":"Hello"},
  "3": {"id":"3","name":"World"},
  ...
}

Cependant, j'ai découvert que les navigateurs ne garantissent pas un ordre d'objet particulier lors de leur boucle, donc dans ce qui précède "3" viendrait avant "7". Je suis passé à l'utilisation d'un format de tableau comme celui-ci:

[
  {"id":"7","name":"Hello"},
  {"id":"3","name":"World"},
  ...
]

Maintenant, je peux boucler dans le bon ordre mais je ne peux pas faire de recherches rapides, par exemple data["3"] sans avoir à parcourir le tableau.

Existe-t-il un bon moyen de combiner les deux approches? Je préfère éviter d'utiliser un objet séparé pour chaque format, car l'objet est assez grand (des centaines d'éléments).

54
DisgruntledGoat

J'ai également rencontré ce problème. Une solution consiste à conserver un tableau ordonné de clés en plus de l'objet d'origine.

var objects = {
  "7": {"id":"7","name":"Hello"},
  "3": {"id":"3","name":"World"},
  ...
}
var order = [ "3", "7", ... ];

Maintenant, si vous voulez le deuxième élément, vous pouvez faire cette recherche:

var second_object = objects[order[1]];

La norme ECMA ne dit rien sur l'ordre des éléments dans un objet. Et en particulier Chrome réorganise les clés quand elles ressemblent à chiffres. Exemple:

var example = {
    "a": "a",
    "b": "b",
    "1": "1",
    "2": "2"
};

si vous imprimez ceci en Chrome obtiendra quelque chose comme:

{
    1: "1",
    2: "2",
    "a": "a",
    "b": "b"
};

C'est un peu aigre .. mais la vie.

Vous pouvez également utiliser la solution liée par Andy, en regroupant ces deux éléments dans un seul objet.

Une alternative que j'utilise beaucoup est une fonction de carte personnalisée qui vous permet de spécifier l'ordre dans lequel l'objet est traversé. En règle générale, vous effectuez un tri lorsque vous imprimez vos données à l'utilisateur, donc pendant que vous bouclez et créez vos lignes de table (par exemple), votre itérateur passera les lignes dans l'ordre spécifié par votre fonction de tri. Je pensais que c'était une bonne idée :)

La signature ressemble à:

function map(object, callback, sort_function);

Exemple d'utilisation:

map(object, function (row) {
   table.add_row(row.header, row.value);
}, function (key1, key2) {
   return object[key1] - object[key2];
});
73
Halcyon