37 votes

Comment trier un objet Javascript, ou le convertir en tableau ?

J'ai des données JSON que je reçois d'un serveur. Dans mon JavaScript, je veux effectuer un tri sur ces données. Je pense que la fonction sort() fera ce que je veux.

Cependant, il semble que Javascript convertisse les données JSON en objets dès leur arrivée. Si j'essaie d'utiliser la méthode sort(), j'obtiens de nombreuses erreurs (en utilisant Firebug pour les tests).

J'ai cherché sur le net, et tout le monde semble dire que, d'une part, les objets JSON sont déjà des tableaux Javascript, et d'autre part que les objets peuvent être traités comme des tableaux. Comme sur cette question où, dans l'une des réponses, un type dit "L'objet [Object] est votre donnée - vous pouvez y accéder comme vous le feriez avec un tableau".

Cependant, ce n'est pas tout à fait vrai. Javascript ne me laisse pas utiliser sort() sur mon objet. Et comme l'hypothèse par défaut est qu'il s'agit de la même chose, il ne semble pas y avoir d'instructions sur la façon de convertir un objet en tableau, ou de forcer Javacript à le traiter comme tel, ou quoi que ce soit d'autre.

Alors... comment faire pour que Javascript me laisse traiter ces données comme un tableau et les trier ?

La sortie du journal de la console de mon objet ressemble à ceci (je veux pouvoir trier par les valeurs du "niveau") :

OBJET JSONdata

{ 
1: {
    displayName: "Dude1",
    email: "dude1@example.com<mailto:dude1@example.com>",
    lastActive: 1296980700, 
    level: 57, 
    timeout: 12969932837
}, 2: {
    displayName: "Dude2",
    email: "dude2@example.com<mailto:dude2@example.com>",
    lastActive: 1296983456,
    level: 28,
    timeout: 12969937382
}, 3: {
    displayName: "Dude3",
    email: "dude3@example.com<mailto:dude3@example.com>",
    lastActive: 1296980749,
    level: 99,
    timeout: 129699323459
} 
}

42voto

Raynos Points 82706

Array.prototype.slice.call(arrayLikeObject)

est la manière standard de convertir un objet de type tableau en tableau.

Cela ne fonctionne vraiment que pour le arguments objet. La conversion d'un objet générique en un tableau est un peu difficile. Voici la source de underscore.js :

_.toArray = function(iterable) {
    if (!iterable)                return [];
    if (iterable.toArray)         return iterable.toArray();
    if (_.isArray(iterable))      return iterable;
    if (_.isArguments(iterable))  return slice.call(iterable);
    return _.values(iterable);
};

_.values = function(obj) {
    return _.map(obj, _.identity);
};

Il s'avère que vous allez devoir boucler sur votre objet et le mettre dans un tableau vous-même.

var newArray = []
for (var key in object) {
    newArray.push(key);
}

Vous confondez les concepts de tableaux et de "tableaux associatifs". En JavaScript, les objets agissent en quelque sorte comme un tableau associatif puisque vous pouvez accéder aux données au format object["key"] . Ce ne sont pas de véritables tableaux associatifs puisque les objets sont des listes non ordonnées.

Les objets et les tableaux sont très différents.

Un exemple d'utilisation de l'underscore :

var sortedObject = _.sortBy(object, function(val, key, object) {
    // return an number to index it by. then it is sorted from smallest to largest number
    return val;
});

Voir exemple concret

7voto

alex Points 186293

Vous devriez être en mesure de convertir un objet JavaScript en un tableau comme suit...

var obj = {
    '1': 'a',
    '2': 'b',
    '3': 'c'  
};

var arr = [];

for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      arr.push(obj[key]);  
    }
}

console.log(arr); // ["a", "b", "c"]

Voir sur jsFiddle .

6voto

Luc125 Points 3144

Si votre objet JavaScript est un objet de type tableau c'est-à-dire une instance d'objet avec une valeur numérique valide. length vous pouvez alors utiliser directement plusieurs indigène Les méthodes Array sur celui-ci grâce à la call méthode. Par exemple :

// Sorts the given objet in-place as if it was an array
Array.prototype.sort.call(yourObject);

Ainsi, si vous connaissez le nombre d'entrées à trier ( Comment compter efficacement le nombre de clés/propriétés d'un objet en JavaScript ? ), vous pouvez le faire :

yourObject.length = theNumberOfEntries;
Array.prototype.sort.call(yourObject);
// Optionally: delete yourObject.length;

Notez que ceci ne triera que les propriétés indexées par "0", "1", "2", ... à length - 1 inclusive, comme dans un tableau. Les autres propriétés de l'objet ne seront pas réordonnées.

2voto

charlysisto Points 2467

Je suis tombé sur ce problème récemment en essayant de regrouper un tableau d'objets par l'une de ses propriétés, ce qui a donné un objet que je ne pouvais donc pas trier.

Concrètement, il s'agit d'un tableau d'articles de blog que je voulais regrouper par année et trier par années décroissantes. J'ai utilisé l'utilitaire de underscore :

var grouped = _.groupBy(blogposts, function(post){
  var date = new Date(post.publication_date)
  return date.getFullYear()
})
//=> { 2010: [blogpost, blogpost,etc], 2011: [blogpost, etc] }

Comme @Raynos l'a expliqué, je devais d'abord obtenir une sorte de tableau avant de le trier...

Il s'avère que underscore (1.4) possède un petit utilitaire sympa appelé pairs qui transformera les {key : value} de votre objet en un tableau de [key, value]. L'équivalent de :

var paired = _.map(grouped, function(val, key){
  return [key, val]
})
//=> [ [2010, [blogpost, blogpost, ...] ], [2011, [blogpost, blogpost, ...]]...]

À partir de là, vous pouvez facilement trier par le premier terme de chaque paire.

Voici le résultat final :

var grouped = _.groupBy(result.resource, function(resource){
  var date = new Date(resource.pub_date)
  return date.getFullYear() //+ "." + (date.getMonth()+1)
})

var paired = _.pairs(grouped)

var sorted = _.sortBy(paired, function(pairs){
  return -parseInt(pairs[0])
})

return sorted;
// Giving me the expected result:
//=> [ [2013, [blogpost, blogpost, ...] ], [2012, [blogpost, blogpost, ...]]...]

Je suis sûr qu'il existe un moyen plus efficace et plus performant, mais venant de ruby, ce code est immédiatement compréhensible pour moi.

1voto

chim Points 1799

JQuery propose une fonction map, qui parcourt chaque élément d'un tableau ou d'un objet et place les résultats dans un nouveau tableau.

Avant jQuery 1.6, $.map() ne permettait de parcourir que des tableaux.

Nous pouvons l'utiliser pour convertir n'importe quel objet en tableau comme suit...

  myArray = $.map(myObject, function (el) {
    return el;
  });

Mais... si la fonction de rappel renvoie nul ou indéfini alors cette valeur est supprimé à partir du tableau. Dans la plupart des cas, cela est utile, mais cela peut poser des problèmes si vous avez besoin de valeurs nulles dans mon tableau.

jQuery offre une solution pour cela... retourner la valeur sous forme de tableau avec la valeur unique

myArrayWithNulls = jQuery.map(myObject, function (el) {
  return [el];
});

Voici un bidouillage démontrant les deux approches : http://jsfiddle.net/chim/nFyPE/

http://jsperf.com/object-to-array-jquery-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