web-dev-qa-db-fra.com

Tri des objets JavaScript par valeur de propriété

Si j'ai un objet JavaScript tel que:

var list = {
  "you": 100, 
  "me": 75, 
  "foo": 116, 
  "bar": 15
};

Existe-t-il un moyen de trier les propriétés en fonction de la valeur? Pour que je me retrouve avec

list = {
  "bar": 15, 
  "me": 75, 
  "you": 100, 
  "foo": 116
};
528
Steerpike

Déplacez-les dans un tableau, triez ce tableau, puis utilisez-le à vos fins. Voici une solution:

var maxSpeed = {
    car: 300, 
    bike: 60, 
    motorbike: 200, 
    airplane: 1000,
    helicopter: 400, 
    rocket: 8 * 60 * 60
};
var sortable = [];
for (var vehicle in maxSpeed) {
    sortable.Push([vehicle, maxSpeed[vehicle]]);
}

sortable.sort(function(a, b) {
    return a[1] - b[1];
});

//[["bike", 60], ["motorbike", 200], ["car", 300],
//["helicopter", 400], ["airplane", 1000], ["rocket", 28800]]

Une fois que vous avez le tableau, vous pouvez reconstruire l'objet à partir du tableau dans l'ordre de votre choix, réalisant ainsi exactement ce que vous avez décidé de faire. Cela fonctionnerait dans tous les navigateurs que je connaisse, mais cela dépendrait d'un problème d'implémentation de la mise en œuvre et pourrait se rompre à tout moment. Vous ne devez jamais faire de suppositions sur l'ordre des éléments dans un objet JavaScript.

563
Nosredna

Nous ne voulons pas dupliquer la structure de données complète, ni utiliser un tableau où nous avons besoin d'un tableau associatif.

Voici une autre façon de faire la même chose que bonna:

var list = {"you": 100, "me": 75, "foo": 116, "bar": 15};
keysSorted = Object.keys(list).sort(function(a,b){return list[a]-list[b]})
console.log(keysSorted);     // bar,me,you,foo

342
Markus R

Vos objets peuvent avoir n'importe quelle quantité de propriétés et vous pouvez choisir de les trier selon la propriété, le nombre ou la chaîne de votre choix si vous placez les objets dans un tableau. Considérez ce tableau:

var arrayOfObjects = [   
    {
        name: 'Diana',
        born: 1373925600000, // Mon, Jul 15 2013
        num: 4,
        sex: 'female'
    },
    {

        name: 'Beyonce',
        born: 1366832953000, // Wed, Apr 24 2013
        num: 2,
        sex: 'female'
    },
    {            
        name: 'Albert',
        born: 1370288700000, // Mon, Jun 3 2013
        num: 3,
        sex: 'male'
    },    
    {
        name: 'Doris',
        born: 1354412087000, // Sat, Dec 1 2012
        num: 1,
        sex: 'female'
    }
];

trier par date de naissance, le plus vieux en premier

// use slice() to copy the array and not just make a reference
var byDate = arrayOfObjects.slice(0);
byDate.sort(function(a,b) {
    return a.born - b.born;
});
console.log('by date:');
console.log(byDate);

trier par nom

var byName = arrayOfObjects.slice(0);
byName.sort(function(a,b) {
    var x = a.name.toLowerCase();
    var y = b.name.toLowerCase();
    return x < y ? -1 : x > y ? 1 : 0;
});

console.log('by name:');
console.log(byName);

http://jsfiddle.net/xsM5s/16/

163
inorganik

Par souci d'exhaustivité, cette fonction renvoie tableau trié de propriétés d'objet:

function sortObject(obj) {
    var arr = [];
    for (var prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            arr.Push({
                'key': prop,
                'value': obj[prop]
            });
        }
    }
    arr.sort(function(a, b) { return a.value - b.value; });
    //arr.sort(function(a, b) { a.value.toLowerCase().localeCompare(b.value.toLowerCase()); }); //use this to sort as strings
    return arr; // returns array
}

var list = {"you": 100, "me": 75, "foo": 116, "bar": 15};
var arr = sortObject(list);
console.log(arr); // [{key:"bar", value:15}, {key:"me", value:75}, {key:"you", value:100}, {key:"foo", value:116}]

Jsfiddle avec le code ci-dessus est ici . Cette solution est basée sur cet article .

Le violon mis à jour pour le tri des chaînes est ici. Vous pouvez supprimer les deux conversions supplémentaires .toLowerCase () pour une comparaison de chaînes sensible à la casse.

58
Stano

Les objets JavaScript ne sont pas ordonnés par définition (voir le Langage ECMAScript Spécification , section 8.6). La spécification de langue ne garantit même pas que, si vous parcourez les propriétés d'un objet deux fois de suite, elles apparaîtront dans le même ordre une seconde fois.

Si vous souhaitez que les choses soient commandées, utilisez un tableau et la méthode Array.prototype.sort.

36
NickFitz

Une version "fléchée" de @marcusR's answer for reference

var myObj = {"you": 100, "me": 75, "foo": 116, "bar": 15};
keysSorted = Object.keys(myObj).sort((a,b) => myObj[a]-myObj[b])
alert(keysSorted);     // bar,me,you,foo

MISE À JOUR: avril 2017 - Ceci retourne un objet myObj trié défini ci-dessus.

Object
 .keys(myObj)
 .sort((a, b) => myObj[a]-myObj[b])
 .reduce((_sortedObj, key) => ({
   ..._sortedObj, 
   [key]: myObj[key]
 }), {})

Essayez ici!

UPDATE: octobre 2018 - Version Object.entries

Object
 .entries(myObj)
 .sort()
 .reduce((_sortedObj, [k,v]) => ({
   ..._sortedObj, 
   [k]: v
 }), {})

Essayez ici!

27
Jason J. Nathan

OK, comme vous le savez peut-être, javascript a la fonction sort (), pour trier les tableaux, mais rien pour les objets ...

Donc, dans ce cas, nous devons d’une manière ou d’une autre obtenir un tableau des clés et les trier, c’est la raison pour laquelle apis vous donne la plupart du temps des objets dans un tableau, car Array a plus de fonctions natives pour y jouer que le littéral d’objet, de toute façon, la solution rapide utilise Object.key qui renvoie un tableau des clés d’objet, je crée la fonction ES6 ci-dessous qui effectue le travail à votre place, elle utilise la méthode native sort ( ) et réduire () fonctions en javascript:

function sortObject(obj) {
  return Object.keys(obj)
    .sort().reduce((a, v) => {
    a[v] = obj[v];
    return a; }, {});
}

Et maintenant, vous pouvez l'utiliser comme ceci:

let myObject = {a: 1, c: 3, e: 5, b: 2, d: 4};
let sortedMyObject = sortObject(myObject);

Vérifiez le sortMyObject et vous pouvez voir le résultat trié par les clés comme ceci:

{a: 1, b: 2, c: 3, d: 4, e: 5}

De même, l’objet principal ne sera pas touché et nous obtiendrons un nouvel objet.

Je crée également l'image ci-dessous, pour rendre les étapes de la fonction plus claires, au cas où vous auriez besoin de la modifier un peu pour la faire à votre manière:

 Sorting a javascript object by property value

20
Alireza

ECMAScript 2017 introduit Object.values / Object.entries . Comme son nom l'indique, le premier agrège toutes les valeurs d'un objet dans un tableau et le second fait l'objet entier dans un tableau de tableaux [key, value]; L'équivalent en python de dict.values() et dict.items() .

Les fonctionnalités facilitent le tri de tout hachage en un objet commandé. À ce jour, seule une petite partie des plateformes JavaScript les prend en charge , mais vous pouvez l'essayer sur Firefox 47+.

let obj = {"you": 100, "me": 75, "foo": 116, "bar": 15};

let entries = Object.entries(obj);
// [["you",100],["me",75],["foo",116],["bar",15]]

let sorted = entries.sort((a, b) => a[1] - b[1]);
// [["bar",15],["me",75],["you",100],["foo",116]]
17
kiding
var list = {
    "you": 100, 
    "me": 75, 
    "foo": 116, 
    "bar": 15
};

function sortAssocObject(list) {
    var sortable = [];
    for (var key in list) {
        sortable.Push([key, list[key]]);
    }

    sortable.sort(function(a, b) {
        return (a[1] < b[1] ? -1 : (a[1] > b[1] ? 1 : 0));
    });

    var orderedList = {};
    for (var i = 0; i < sortable.length; i++) {
        orderedList[sortable[i][0]] = sortable[i][1];
    }

    return orderedList;
}

sortAssocObject(list);

// {bar: 15, me: 75, you: 100, foo: 116}
7
Vasil Nikolov

Underscore.js ou Lodash.js pour le tri avancé d'objets ou de tableaux

 var data={
        "models": {

            "LTI": [
                "TX"
            ],
            "Carado": [
                "A",
                "T",
                "A(пасс)",
                "A(груз)",
                "T(пасс)",
                "T(груз)",
                "A",
                "T"
            ],
            "SPARK": [
                "SP110C 2",
                "sp150r 18"
            ],
            "Autobianchi": [
                "A112"
            ]
        }
    };

    var arr=[],
        obj={};
    for(var i in data.models){
      arr.Push([i, _.sortBy(data.models[i],function (el){return el;})]);
    }
    arr=_.sortBy(arr,function (el){
      return el[0];
    });
    _.map(arr,function (el){return obj[el[0]]=el[1];});
     console.log(obj);

démo

6
Roman Yudin

Mise à jour avec ES6: Si votre problème est de pouvoir parcourir un objet trié (c'est pourquoi j'imagine que vous souhaitez que vos propriétés d'objet soient triées), vous pouvez utiliser l'objet Map

Vous pouvez insérer vos paires (clé, valeur) dans un ordre trié puis faire une boucle for..of va garantir les avoir en boucle dans l'ordre où vous les avez insérées

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (var [key, value] of myMap) {
  console.log(key + " = " + value);
}
// 0 = zero 
// 1 = one
6
julianljk

Je suis la solution donnée par slebetman } _ (allez la lire pour tous les détails), mais ajusté, car votre objet est non-imbriqué.

// First create the array of keys/values so that we can sort it:
var sort_array = [];
for (var key in list) {
    sort_array.Push({key:key,value:list[key]});
}

// Now sort it:
sort_array.sort(function(x,y){return x.value - y.value});

// Now process that object with it:
for (var i=0;i<sort_array.length;i++) {
    var item = list[sort_array[i].key];

    // now do stuff with each item
}
5
bonna

Cela pourrait être un moyen simple de le gérer comme un véritable objet ordonné. Je ne sais pas à quel point c'est lent. pourrait également être mieux avec une boucle while.

Object.sortByKeys = function(myObj){
  var keys = Object.keys(myObj)
  keys.sort()
  var sortedObject = Object()
  for(i in keys){
    key = keys[i]
    sortedObject[key]=myObj[key]
   }

  return sortedObject

}

Et puis j'ai trouvé cette fonction inversion de: http://nelsonwells.net/2011/10/swap-object-key-and-values-in-javascript/

Object.invert = function (obj) {

  var new_obj = {};

  for (var prop in obj) {
    if(obj.hasOwnProperty(prop)) {
      new_obj[obj[prop]] = prop;
    }
  }

  return new_obj;
};

Alors 

var list = {"you": 100, "me": 75, "foo": 116, "bar": 15};
var invertedList = Object.invert(list)
var invertedOrderedList = Object.sortByKeys(invertedList)
var orderedList = Object.invert(invertedOrderedList)
2
Carson Wright

de nombreuses fonctions similaires et utiles: https://github.com/shimondoodkin/groupbyfunctions/

function sortobj(obj)
{
    var keys=Object.keys(obj);
    var kva= keys.map(function(k,i)
    {
        return [k,obj[k]];
    });
    kva.sort(function(a,b){
        if(a[1]>b[1]) return -1;if(a[1]<b[1]) return 1;
        return 0
    });
    var o={}
    kva.forEach(function(a){ o[a[0]]=a[1]})
    return o;
}

function sortobjkey(obj,key)
{
    var keys=Object.keys(obj);
    var kva= keys.map(function(k,i)
    {
        return [k,obj[k]];
    });
    kva.sort(function(a,b){
        k=key;      if(a[1][k]>b[1][k]) return -1;if(a[1][k]<b[1][k]) return 1;
        return 0
    });
    var o={}
    kva.forEach(function(a){ o[a[0]]=a[1]})
    return o;
}
1
Shimon Doodkin

Objet trié par valeur (DESC)

function sortObject(list) {
  var sortable = [];
  for (var key in list) {
    sortable.Push([key, list[key]]);
  }

  sortable.sort(function(a, b) {
    return (a[1] > b[1] ? -1 : (a[1] < b[1] ? 1 : 0));
  });

  var orderedList = {};
  for (var i = 0; i < sortable.length; i++) {
    orderedList[sortable[i][0]] = sortable[i][1];
  }

  return orderedList;
}
1
victorhazbun

Voici un autre exemple:

function sortObject(obj) {
  var arr = [];
  var prop;
  for (prop in obj) {
    if (obj.hasOwnProperty(prop)) {
      arr.Push({
        'key': prop,
        'value': obj[prop]
      });
    }
  }
  arr.sort(function(a, b) {
    return a.value - b.value;
  });
  return arr; // returns array
}
var list = {
  car: 300,
  bike: 60,
  motorbike: 200,
  airplane: 1000,
  helicopter: 400,
  rocket: 8 * 60 * 60
};
var arr = sortObject(list);
console.log(arr);

1

En utilisant query-js vous pouvez le faire comme ceci

list.keys().select(function(k){
    return {
        key: k,
        value : list[k]
    }
}).orderBy(function(e){ return e.value;});

Vous pouvez trouver un article d'introduction sur query-js ici

0
Rune FS

Une autre façon de résoudre ceci: -

var res = [{"s1":5},{"s2":3},{"s3":8}].sort(function(obj1,obj2){ 
 var prop1;
 var prop2;
 for(prop in obj1) {
  prop1=prop;
 }
 for(prop in obj2) {
  prop2=prop;
 }
 //the above two for loops will iterate only once because we use it to find the key
 return obj1[prop1]-obj2[prop2];
});

// res aura le tableau de résultats

0
vivek_nk

Très court et simple!

      var sortedList = {};
  Object.keys(list).sort((a,b)=>{return list[a]-list[b]}).forEach((key) => {
    sortedList[key] = list[key];
  })
0
Maryam Koulaei

Essaye ça. Même votre objet n'a pas la propriété sur laquelle vous essayez de trier, il sera également traité. 

Appelez-le simplement en envoyant une propriété avec un objet. 

var sortObjectByProperty = function(property,object){

    console.time("Sorting");
    var  sortedList      = [];
         emptyProperty   = [];
         tempObject      = [];
         nullProperty    = [];
    $.each(object,function(index,entry){
        if(entry.hasOwnProperty(property)){
            var propertyValue = entry[property];
            if(propertyValue!="" && propertyValue!=null){
              sortedList.Push({key:propertyValue.toLowerCase().trim(),value:entry});  
            }else{
                emptyProperty.Push(entry);
           }
        }else{
            nullProperty.Push(entry);
        }
    });

      sortedList.sort(function(a,b){
           return a.key < b.key ? -1 : 1;
         //return a.key < b.key?-1:1;   // Asc 
         //return a.key < b.key?1:-1;  // Desc
      });


    $.each(sortedList,function(key,entry){
        tempObject[tempObject.length] = entry.value;
     });

    if(emptyProperty.length>0){
        tempObject.concat(emptyProperty);
    }
    if(nullProperty.length>0){
        tempObject.concat(nullProperty);
    }
    console.timeEnd("Sorting");
    return tempObject;
}
0
Vali Shah
function sortObjByValue(list){
 var sortedObj = {}
 Object.keys(list)
  .map(key => [key, list[key]])
  .sort((a,b) => a[1] > b[1] ? 1 : a[1] < b[1] ? -1 : 0)
  .forEach(data => sortedObj[data[0]] = data[1]);
 return sortedObj;
}
sortObjByValue(list);

Github Gist Lien

0
Ankit Sinha

voici le moyen d'obtenir trier l'objet et obtenir l'objet trié en retour

let sortedObject = {}
sortedObject = Object.keys(yourObject).sort((a, b) => {
                        return yourObject[a] - yourObject[b] 
                    }).reduce((prev, curr, i) => {
                        prev[i] = yourObject[curr]
                        return prev
                    }, {});

vous pouvez personnaliser votre fonction de tri selon vos besoins

0
Ashutosh Ranjan
var list = {
    "you": 100,
    "me": 75,
    "foo": 116,
    "bar": 15
};
var tmpList = {};
while (Object.keys(list).length) {
    var key = Object.keys(list).reduce((a, b) => list[a] > list[b] ? a : b);
    tmpList[key] = list[key];
    delete list[key];
}
list = tmpList;
console.log(list); // { foo: 116, you: 100, me: 75, bar: 15 }
0
Milad Aslani

Trier les valeurs sans plusieurs boucles for (pour trier les clés, changez l'index dans le rappel de tri en "0")

const list = {
    "you": 100, 
    "me": 75, 
    "foo": 116, 
    "bar": 15
  };

let sorted = Object.fromEntries(
                Object.entries(list).sort( (a,b) => a[1] - b[1] )    
             ) 
console.log('Sorted object: ', sorted) 
0
dino4udo

Je ne trouve pas la réponse ci-dessus qui fonctionnerait et qui serait à la fois PETIT, et prendrait en charge les objets imbriqués (pas les tableaux), alors j’ai écrit le mien :) Fonctionne à la fois avec des chaînes et des entiers.

  function sortObjectProperties(obj, sortValue){
      var keysSorted = Object.keys(obj).sort(function(a,b){return obj[a][sortValue]-obj[b][sortValue]});
      var objSorted = {};
      for(var i = 0; i < keysSorted.length; i++){
          objSorted[keysSorted[i]] = obj[keysSorted[i]];
      }
      return objSorted;
    }

Usage:

    /* sample object with unsorder properties, that we want to sort by 
    their "customValue" property */

    var objUnsorted = {
       prop1 : {
          customValue : 'ZZ'
       },
       prop2 : {
          customValue : 'AA'
       }
    }

    // call the function, passing object and property with it should be sorted out
    var objSorted = sortObjectProperties(objUnsorted, 'customValue');

    // now console.log(objSorted) will return:
    { 
       prop2 : {
          customValue : 'AA'
       },
       prop1 : {
          customValue : 'ZZ'
       } 
    }
0
Paul Walczewski

Juste au cas où quelqu'un voudrait conserver l'objet (avec les clés et les valeurs), en utilisant le code de référence de @Markus R et le commentaire @James Moran, il suffit d'utiliser:

var list = {"you": 100, "me": 75, "foo": 116, "bar": 15};
var newO = {};
Object.keys(list).sort(function(a,b){return list[a]-list[b]})
                 .map(key => newO[key] = list[key]);
console.log(newO);  // {bar: 15, me: 75, you: 100, foo: 116}
0
esneyderp

J'ai créé un plugin juste pour cela, il accepte 1 arg qui est un objet non trié, et retourne un objet qui a été trié par prop. Cela fonctionnera sur tous les objets en 2 dimensions tels que {"Nick": 28, "Bob": 52}...

var sloppyObj = {
    'C': 78,
    'A': 3,
    'B': 4
};

// Extend object to support sort method
function sortObj(obj) {
    "use strict";

    function Obj2Array(obj) {
        var newObj = [];
        for (var key in obj) {
            if (!obj.hasOwnProperty(key)) return;
            var value = [key, obj[key]];
            newObj.Push(value);
        }
        return newObj;
    }

    var sortedArray = Obj2Array(obj).sort(function(a, b) {
        if (a[1] < b[1]) return -1;
        if (a[1] > b[1]) return 1;
        return 0;
    });

    function recreateSortedObject(targ) {
        var sortedObj = {};
        for (var i = 0; i < targ.length; i++) {
            sortedObj[targ[i][0]] = targ[i][1];
        }
        return sortedObj;
    }
    return recreateSortedObject(sortedArray);
}

var sortedObj = sortObj(sloppyObj);

alert(JSON.stringify(sortedObj));

Voici une démonstration de la fonction fonctionnant comme prévuhttp://codepen.io/nicholasabrams/pen/RWRqve?editors=001

0
Alpha G33k

Merci et continuez à répondre à @Nosredna

Maintenant que nous comprenons que les objets doivent être convertis en tableau, triez le tableau. c'est utile pour trier un tableau (ou un objet converti en tableau) par chaîne: 

Object {6: Object, 7: Object, 8: Object, 9: Object, 10: Object, 11: Object, 12: Object}
   6: Object
   id: "6"
   name: "PhD"
   obe_service_type_id: "2"
   __proto__: Object
   7: Object
   id: "7"
   name: "BVC (BPTC)"
   obe_service_type_id: "2"
   __proto__: Object


    //Sort options
    var sortable = [];
    for (var vehicle in options)
    sortable.Push([vehicle, options[vehicle]]);
    sortable.sort(function(a, b) {
        return a[1].name < b[1].name ? -1 : 1;
    });


    //sortable => prints  
[Array[2], Array[2], Array[2], Array[2], Array[2], Array[2], Array[2]]
    0: Array[2]
    0: "11"
    1: Object
        id: "11"
        name: "AS/A2"
        obe_service_type_id: "2"
        __proto__: Object
        length: 2
        __proto__: Array[0]
    1: Array[2]
    0: "7"
    1: Object
        id: "7"
        name: "BVC (BPTC)"
        obe_service_type_id: "2"
        __proto__: Object
        length: 2
0
Fury