web-dev-qa-db-fra.com

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 faire un tri sur elle. Je pense que la fonction sort () fera ce que je veux.

Cependant, il semble que JavaScript convertisse les données JSON en un objet immédiatement à l'arrivée. Si j'essaie d'utiliser la méthode sort (), j'obtiens beaucoup d'erreurs (en utilisant Firebug pour les tests).

J'ai parcouru le réseau et tout le monde semble dire que, d'une part, les objets JSON sont déjà des tableaux JavaScript, mais aussi que les objets peuvent être traités comme des tableaux. Comme ci-dessus cette question , où, dans l’une des réponses, un gars dit: "L’objet [objet]] est votre donnée - vous pouvez y accéder comme un tableau."

Cependant, ce n'est pas tout à fait vrai. JavaScript ne me permettra pas d'utiliser sort () sur mon objet. Et comme l'hypothèse par défaut est que ce sont tous la même chose, il ne semble y avoir aucune instruction sur la conversion d'un objet en tableau, ni forcer JavaScript à le traiter comme tel, ou quelque chose du genre.

Alors ... comment obtenir JavaScript pour me permettre de traiter ces données comme un tableau et de 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: "[email protected]<mailto:[email protected]>",
    lastActive: 1296980700, 
    level: 57, 
    timeout: 12969932837
}, 2: {
    displayName: "Dude2",
    email: "[email protected]<mailto:[email protected]>",
    lastActive: 1296983456,
    level: 28,
    timeout: 12969937382
}, 3: {
    displayName: "Dude3",
    email: "[email protected]<mailto:[email protected]>",
    lastActive: 1296980749,
    level: 99,
    timeout: 129699323459
} 
}
37
Questioner

Vous devriez être capable de convertir un objet JavaScript dans un tableau comme celui-ci ...

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 .

7
alex

Si votre objet JavaScript est un objet de type array-like, c'est-à-dire une instance d'objet avec une propriété numérique valide length, vous pouvez directement utiliser de nombreuses méthodes native Array grâce à la méthode call. . Par exemple:

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

Donc, 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 faire:

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

Notez que cela ne fera que trier les propriétés indexées par "0", "1", "2", ... en length - 1 inclus, comme dans un tableau. Les autres propriétés de l'objet ne seront pas réorganisées.

6
Luc125

La plupart de ces réponses compliquent excessivement le problème ou utilisent JQuery ou Underscore alors que le PO ne l’a jamais demandé.

Vous pouvez convertir un objet en un tableau comme ceci:

myArray= Object.keys(data).map(function(key) { return data[key] });

Et triez le résultat comme ceci:

myArray.sort(function(x, y) {return x.level - y.level});

Si vous avez besoin de l'id/index, alors vous devez en faire un peu plus:

Object.keys(data).map(function(key) { 
  var obj = data[key];
  obj.index = key;
  return obj 
});
5
andyhasit

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

Concrètement, c’est un ensemble d’articles de blog que je voulais regrouper par année et les trier par années décroissantes. J'ai utilisé l'utilitaire de soulignement:

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 disposer d'une sorte de tableau avant de le trier ... 

Il s'avère que le trait de soulignement (1.4) a un petit utilitaire appelé pairs qui mappera la {clé: valeur} de votre objet dans un tableau de [clé, valeur]. L'équivalent de:

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

A 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 une méthode plus efficace et plus performante, mais si je viens de Ruby, ce code est immédiatement compréhensible pour moi.

2
charlysisto

jQuery propose une fonction de carte qui parcourt chaque élément d’un tableau ou d’un objet et mappe les résultats dans un nouveau tableau. 

Avant jQuery 1.6, $ .map () ne supportait que les tableaux.

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

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

Mais ... Si la fonction de rappel retourne null ou undefined, alors cette valeur est remove du tableau, dans la plupart des cas, cela est utile, mais cela peut poser problème si vous avez besoin de valeurs null dans myArray.

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

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

Voici un violon montrant les deux approches: http://jsfiddle.net/chim/nFyPE/

http://jsperf.com/object-to-array-jquery-2

1
chim

J'ai écrit une petite fonction pour convertir récursivement un objet avec des propriétés qui peuvent aussi être des objets en un tableau multidimensionnel. Ce code dépend du soulignement ou du lodash pour les méthodes forEach et toArray.

function deepToArray(obj) {
    var copy = [];


    var i = 0;
    if (obj.constructor == Object ||
        obj.constructor == Array) {

        _.forEach(obj, process);

    } else {

        copy = obj;

    }


    function process(current, index, collection) {

        var processed = null;
        if (current.constructor != Object &&
            current.constructor != Array) {
            processed = current;
        } else {
            processed = deepToArray(_.toArray(current));
        }

        copy.Push(processed);

    }

    return copy;
}

Voici le violon: http://jsfiddle.net/gGT2D/

Remarque: Ceci a été écrit pour convertir un objet qui était à l'origine un tableau en un tableau, ainsi toutes les valeurs de clé d'index non-tableau seront perdues.

1
Isioma Nnodum