Ordina array di oggetti per valore di proprietà stringa in JavaScript

Ho una matrice di oggetti JavaScript:

var objs = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ]; 

Come posso ordinarli in base al valore di last_nom in JavaScript?

So di sort(a,b) , ma sembra funzionare solo su stringhe e numeri. Devo aggiungere un metodo toString ai miei oggetti?

È abbastanza facile scrivere la tua funzione di confronto:

 function compare(a,b) { if (a.last_nom < b.last_nom) return -1; if (a.last_nom > b.last_nom) return 1; return 0; } objs.sort(compare); 

O in linea (c / o Marco Demaio):

 objs.sort(function(a,b) {return (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0);} ); 

Puoi anche creare una funzione di ordinamento dinamico che ordina gli oggetti in base al loro valore che hai passato:

 function dynamicSort(property) { var sortOrder = 1; if(property[0] === "-") { sortOrder = -1; property = property.substr(1); } return function (a,b) { var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0; return result * sortOrder; } } 

Quindi puoi avere una serie di oggetti come questo:

 var People = [ {Name: "Name", Surname: "Surname"}, {Name:"AAA", Surname:"ZZZ"}, {Name: "Name", Surname: "AAA"} ]; 

… e funzionerà quando lo fai:

 People.sort(dynamicSort("Name")); People.sort(dynamicSort("Surname")); People.sort(dynamicSort("-Surname")); 

In realtà questo già risponde alla domanda. Qui sotto parte è scritta perché molte persone mi hanno contattato, lamentandosi che non funziona con più parametri .

Parametri multipli

È ansible utilizzare la funzione seguente per generare funzioni di ordinamento con più parametri di ordinamento.

 function dynamicSortMultiple() { /* * save the arguments object as it will be overwritten * note that arguments object is an array-like object * consisting of the names of the properties to sort by */ var props = arguments; return function (obj1, obj2) { var i = 0, result = 0, numberOfProperties = props.length; /* try getting a different result from 0 (equal) * as long as we have extra properties to compare */ while(result === 0 && i < numberOfProperties) { result = dynamicSort(props[i])(obj1, obj2); i++; } return result; } } 

Che ti consentirebbe di fare qualcosa del genere:

 People.sort(dynamicSortMultiple("Name", "-Surname")); 

Aggiungendolo al prototipo

(L'implementazione che è appena sotto è ispirata alla risposta di Mike R )

Non consiglierei di cambiare un prototipo di un object nativo ma solo di dare un esempio in modo da poterlo implementare sui propri oggetti (Per gli ambienti che lo supportano, puoi anche usare Object.defineProperty come mostrato nella prossima sezione, che almeno non ha l'effetto collaterale negativo di essere enumerabile, come descritto nell'ultima parte)

L'implementazione del prototipo sarebbe simile alla seguente ( Ecco un esempio funzionante ):

 //Don't just copy-paste this code. You will break the "for-in" loops !function() { function _dynamicSortMultiple(attr) { /* dynamicSortMultiple function body comes here */ } function _dynamicSort(property) { /* dynamicSort function body comes here */ } Array.prototype.sortBy = function() { return this.sort(_dynamicSortMultiple.apply(null, arguments)); } }(); 

Il modo "OK" di aggiungerlo al prototipo

Se scegli come target IE v9.0 e versioni successive, come ho già detto, usa Object.defineProperty come questo ( esempio di lavoro ):

 //Won't work below IE9, but totally safe otherwise !function() { function _dynamicSortMultiple(attr) { /* dynamicSortMultiple function body comes here */ } function _dynamicSort(property) { /* dynamicSort function body comes here */ } Object.defineProperty(Array.prototype, "sortBy", { enumerable: false, writable: true, value: function() { return this.sort(_dynamicSortMultiple.apply(null, arguments)); } }); }(); 

Questo può essere un compromesso accettabile fino all'arrivo dell'operatore di bind .

Tutto questo divertimento prototipo consente questo:

 People.sortBy("Name", "-Surname"); 

Dovresti leggere questo

Se si utilizza il metodo di accesso al prototipo diretto (Object.defineProperty va bene) e l'altro codice non controlla hasOwnProperty , i kittens muoiono! Ok, ad essere onesti, nessun gattino arriverà davvero, ma probabilmente le cose si romperanno e ogni altro sviluppatore della tua squadra ti odierà:

il male

Vedi quest'ultimo "SortBy"? Si. Non fantastico Utilizzare Object.defineProperty dove è ansible e lasciare il solo Array.prototype.

underscore.js

usa il trattino basso, è piccolo e fantastico …

sortBy_.sortBy (lista, iteratore, [contesto]) Restituisce una copia ordinata di lista, ordinata in ordine ascendente in base ai risultati dell’esecuzione di ciascun valore tramite iteratore. Iterator può anche essere il nome della stringa della proprietà da ordinare (ad esempio lunghezza).

 var objs = [ { first_nom: 'Lazslo',last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ]; var sortedObjs = _.sortBy( objs, 'first_nom' ); 

Non capisco perché la gente lo rende così complicato:

 objs.sort(function(a, b){ return a.last_nom > b.last_nom; }); 

Per motori più stretti:

 objs.sort(function(a, b){ return a.last_nom == b.last_nom ? 0 : +(a.last_nom > b.last_nom) || -1; }); 

Scambia l’operatore per ordinarlo in ordine alfabetico inverso.

In ES6 / ES2015 o versioni successive puoi procedere in questo modo:

 objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom)); 

Se hai cognomi duplicati potresti ordinarli per nome-

 obj.sort(function(a,b){ if(a.last_nom< b.last_nom) return -1; if(a.last_nom >b.last_nom) return 1; if(a.first_nom< b.first_nom) return -1; if(a.first_nom >b.first_nom) return 1; return 0; }); 

Soluzione semplice e rapida a questo problema utilizzando l’ereditarietà del prototipo:

 Array.prototype.sortBy = function(p) { return this.slice(0).sort(function(a,b) { return (a[p] > b[p]) ? 1 : (a[p] < b[p]) ? -1 : 0; }); } 

Esempio / utilizzo

 objs = [{age:44,name:'vinay'},{age:24,name:'deepak'},{age:74,name:'suresh'}]; objs.sortBy('age'); // Returns // [{"age":24,"name":"deepak"},{"age":44,"name":"vinay"},{"age":74,"name":"suresh"}] objs.sortBy('name'); // Returns // [{"age":24,"name":"deepak"},{"age":74,"name":"suresh"},{"age":44,"name":"vinay"}] 

Aggiornamento: non modifica più la matrice originale.

Invece di utilizzare una funzione di confronto personalizzata, è ansible anche creare un tipo di object con il metodo toString() (che viene richiamato dalla funzione di confronto predefinita):

 function Person(firstName, lastName) { this.firtName = firstName; this.lastName = lastName; } Person.prototype.toString = function() { return this.lastName + ', ' + this.firstName; } var persons = [ new Person('Lazslo', 'Jamf'), ...] persons.sort(); 

Ci sono molte buone risposte qui, ma vorrei sottolineare che possono essere estese molto semplicemente per ottenere un ordinamento molto più complesso. L’unica cosa che devi fare è usare l’operatore OR per concatenare funzioni di comparazione come questa:

 objs.sort((a,b)=> fn1(a,b) || fn2(a,b) || fn3(a,b) ) 

Dove fn1 , fn2 , … sono le funzioni di ordinamento che restituiscono [-1,0,1]. Ciò si traduce in “ordinamento di fn1”, “ordinamento di fn2” che è praticamente uguale a ORDER BY in SQL.

Questa soluzione si basa sul comportamento di || operatore che valuta la prima espressione valutata che può essere convertita in vera .

La forma più semplice ha solo una funzione inline come questa:

 // ORDER BY last_nom objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) ) 

Avendo due passaggi con last_nom , first_nom ordinamento sarebbe simile a questo:

 // ORDER_BY last_nom, first_nom objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) || a.first_nom.localeCompare(b.first_nom) ) 

Una funzione di confronto generica potrebbe essere qualcosa del genere:

 // ORDER BY  let cmp = (a,b,n)=>a[n].localeCompare(b[n]) 

Questa funzione può essere estesa per supportare campi numerici, case sensitive, tipi di dati arbitary, ecc.

Puoi usarli con il concatenarli in base alla priorità di ordinamento:

 // ORDER_BY last_nom, first_nom objs.sort((a,b)=> cmp(a,b, "last_nom") || cmp(a,b, "first_nom") ) // ORDER_BY last_nom, first_nom DESC objs.sort((a,b)=> cmp(a,b, "last_nom") || -cmp(a,b, "first_nom") ) // ORDER_BY last_nom DESC, first_nom DESC objs.sort((a,b)=> -cmp(a,b, "last_nom") || -cmp(a,b, "first_nom") ) 

Il punto qui è che il puro JavaScript con approccio funzionale può portarvi molto tempo senza librerie esterne o codice complesso. È anche molto efficace, dal momento che non è necessario eseguire l’analisi delle stringhe

Esempio di utilizzo:

 objs.sort(sortBy('last_nom')); 

script:

 /** * @description * Returns a function which will sort an * array of objects by the given key. * * @param {String} key * @param {Boolean} reverse * @return {Function} */ function sortBy(key, reverse) { // Move smaller items towards the front // or back of the array depending on if // we want to sort the array in reverse // order or not. var moveSmaller = reverse ? 1 : -1; // Move larger items towards the front // or back of the array depending on if // we want to sort the array in reverse // order or not. var moveLarger = reverse ? -1 : 1; /** * @param {*} a * @param {*} b * @return {Number} */ return function(a, b) { if (a[key] < b[key]) { return moveSmaller; } if (a[key] > b[key]) { return moveLarger; } return 0; }; } 

Lodash.js (superset di Underscore.js )

È opportuno non aggiungere un framework per ogni semplice logica, ma basarsi su framework di utilità ben testati, accelerare lo sviluppo e ridurre la quantità di bug scritti non è un peccato.

Lodash produce codice molto pulito e promuove uno stile di programmazione più funzionale , che si traduce in meno bug. In un lampo diventa chiaro quale sia l’intento se il codice è.

Il problema dell’OP può essere semplicemente risolto come:

 const sortedObjs = _.sortBy(objs, 'last_nom'); 

Ulteriori informazioni? Ad esempio, abbiamo seguente object nidificato:

 const users = [  { 'user': {'name':'fred', 'age': 48}},  { 'user': {'name':'barney', 'age': 36 }},  { 'user': {'name':'wilma'}},  { 'user': {'name':'betty', 'age': 32}} ]; 

Ora possiamo usare la scorciatoia _.property user.age per specificare il percorso della proprietà che deve essere abbinata. Ordineremo gli oggetti utente per la proprietà age nested. Sì, consente la corrispondenza delle proprietà nidificate!

 const sortedObjs = _.sortBy(users, ['user.age']); 

Vuoi invertirlo? Nessun problema. Usa _.reverse .

 const sortedObjs = _.reverse(_.sortBy(users, ['user.age'])); 

Vuoi combinare entrambi usando Chaining ?

 const sortedObjs = _.chain(users).sortBy('user.age').reverse().value(); 

So che questa domanda è troppo vecchia, ma non ho visto alcuna implementazione simile alla mia.
Questa versione è basata sull’idioma di trasformazione di Schwartz .

 function sortByAttribute(array, ...attrs) { // generate an array of predicate-objects contains // property getter, and descending indicator let predicates = attrs.map(pred => { let descending = pred.charAt(0) === '-' ? -1 : 1; pred = pred.replace(/^-/, ''); return { getter: o => o[pred], descend: descending }; }); // schwartzian transform idiom implementation. aka: "decorate-sort-undecorate" return array.map(item => { return { src: item, compareValues: predicates.map(predicate => predicate.getter(item)) }; }) .sort((o1, o2) => { let i = -1, result = 0; while (++i < predicates.length) { if (o1.compareValues[i] < o2.compareValues[i]) result = -1; if (o1.compareValues[i] > o2.compareValues[i]) result = 1; if (result *= predicates[i].descend) break; } return result; }) .map(item => item.src); } 

Ecco un esempio su come usarlo:

 let games = [ { name: 'Pako', rating: 4.21 }, { name: 'Hill Climb Racing', rating: 3.88 }, { name: 'Angry Birds Space', rating: 3.88 }, { name: 'Badland', rating: 4.33 } ]; // sort by one attribute console.log(sortByAttribute(games, 'name')); // sort by mupltiple attributes console.log(sortByAttribute(games, '-rating', 'name')); 

Ordinamento (altro) Matrici complesse di oggetti

Dal momento che probabilmente si incontrano strutture dati più complesse come questo array, vorrei espandere la soluzione.

TL; DR

Sono più una versione pluggable basata sulla risposta molto bella di @ ege-Özcan .

Problema

Ho incontrato il sotto e non ho potuto cambiarlo. Inoltre, non volevo appiattire temporaneamente l’object. Né volevo usare underscore / lodash, principalmente per motivi di prestazioni e il divertimento di implementarlo da solo.

 var People = [ {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"}, {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"}, {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"} ]; 

Obbiettivo

L’objective è di ordinarlo principalmente da People.Name.name e secondariamente da People.Name.surname

ostacoli

Ora, nella soluzione di base utilizza la notazione della parentesi per calcolare le proprietà da ordinare dynamicmente. Qui, però, dovremmo build dynamicmente anche la notazione delle parentesi, poiché ci si aspetterebbe che alcune People['Name.name'] come People['Name.name'] funzionerebbero, il che non funziona.

Semplicemente facendo People['Name']['name'] , d’altra parte, è statico e ti consente solo di scendere al n ° livello.

Soluzione

L’aggiunta principale qui sarà quella di camminare lungo l’albero degli oggetti e determinare il valore dell’ultima foglia, devi specificare, così come ogni foglia intermedia.

 var People = [ {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"}, {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"}, {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"} ]; People.sort(dynamicMultiSort(['Name','name'], ['Name', '-surname'])); // Results in... // [ { Name: { name: 'AAA', surname: 'ZZZ' }, Middlename: 'Abrams' }, // { Name: { name: 'Name', surname: 'Surname' }, Middlename: 'JJ' }, // { Name: { name: 'Name', surname: 'AAA' }, Middlename: 'Wars' } ] // same logic as above, but strong deviation for dynamic properties function dynamicSort(properties) { var sortOrder = 1; // determine sort order by checking sign of last element of array if(properties[properties.length - 1][0] === "-") { sortOrder = -1; // Chop off sign properties[properties.length - 1] = properties[properties.length - 1].substr(1); } return function (a,b) { propertyOfA = recurseObjProp(a, properties) propertyOfB = recurseObjProp(b, properties) var result = (propertyOfA < propertyOfB) ? -1 : (propertyOfA > propertyOfB) ? 1 : 0; return result * sortOrder; }; } /** * Takes an object and recurses down the tree to a target leaf and returns it value * @param {Object} root - Object to be traversed. * @param {Array} leafs - Array of downwards traversal. To access the value: {parent:{ child: 'value'}} -> ['parent','child'] * @param {Number} index - Must not be set, since it is implicit. * @return {String|Number} The property, which is to be compared by sort. */ function recurseObjProp(root, leafs, index) { index ? index : index = 0 var upper = root // walk down one level lower = upper[leafs[index]] // Check if last leaf has been hit by having gone one step too far. // If so, return result from last step. if (!lower) { return upper } // Else: recurse! index++ // HINT: Bug was here, for not explicitly returning function // https://stackoverflow.com/a/17528613/3580261 return recurseObjProp(lower, leafs, index) } /** * Multi-sort your array by a set of properties * @param {...Array} Arrays to access values in the form of: {parent:{ child: 'value'}} -> ['parent','child'] * @return {Number} Number - number for sort algorithm */ function dynamicMultiSort() { var args = Array.prototype.slice.call(arguments); // slight deviation to base return function (a, b) { var i = 0, result = 0, numberOfProperties = args.length; // REVIEW: slightly verbose; maybe no way around because of `.sort`-'s nature // Consider: `.forEach()` while(result === 0 && i < numberOfProperties) { result = dynamicSort(args[i])(a, b); i++; } return result; } } 

Esempio

Esempio di lavoro su JSBin

Ho un pezzo di codice che funziona per me:

 arr.sort((a, b) => a.name > b.name) 

AGGIORNAMENTO: non funziona sempre, quindi non è corretto 🙁

Un modo semplice:

 objs.sort(function(a,b) { return b.last_nom.toLowerCase() < a.last_nom.toLowerCase(); }); 

Vedi che '.toLowerCase()' è necessario per prevenire gli errori nel confronto delle stringhe.

Combinando la soluzione dynamic di Ege con l’idea di Vinay, ottieni una soluzione solida e robusta:

 Array.prototype.sortBy = function() { function _sortByAttr(attr) { var sortOrder = 1; if (attr[0] == "-") { sortOrder = -1; attr = attr.substr(1); } return function(a, b) { var result = (a[attr] < b[attr]) ? -1 : (a[attr] > b[attr]) ? 1 : 0; return result * sortOrder; } } function _getSortFunc() { if (arguments.length == 0) { throw "Zero length arguments not allowed for Array.sortBy()"; } var args = arguments; return function(a, b) { for (var result = 0, i = 0; result == 0 && i < args.length; i++) { result = _sortByAttr(args[i])(a, b); } return result; } } return this.sort(_getSortFunc.apply(null, arguments)); } 

Uso:

 // Utility for printing objects Array.prototype.print = function(title) { console.log("************************************************************************"); console.log("**** "+title); console.log("************************************************************************"); for (var i = 0; i < this.length; i++) { console.log("Name: "+this[i].FirstName, this[i].LastName, "Age: "+this[i].Age); } } // Setup sample data var arrObj = [ {FirstName: "Zach", LastName: "Emergency", Age: 35}, {FirstName: "Nancy", LastName: "Nurse", Age: 27}, {FirstName: "Ethel", LastName: "Emergency", Age: 42}, {FirstName: "Nina", LastName: "Nurse", Age: 48}, {FirstName: "Anthony", LastName: "Emergency", Age: 44}, {FirstName: "Nina", LastName: "Nurse", Age: 32}, {FirstName: "Ed", LastName: "Emergency", Age: 28}, {FirstName: "Peter", LastName: "Physician", Age: 58}, {FirstName: "Al", LastName: "Emergency", Age: 51}, {FirstName: "Ruth", LastName: "Registration", Age: 62}, {FirstName: "Ed", LastName: "Emergency", Age: 38}, {FirstName: "Tammy", LastName: "Triage", Age: 29}, {FirstName: "Alan", LastName: "Emergency", Age: 60}, {FirstName: "Nina", LastName: "Nurse", Age: 54} ]; //Unit Tests arrObj.sortBy("LastName").print("LastName Ascending"); arrObj.sortBy("-LastName").print("LastName Descending"); arrObj.sortBy("LastName", "FirstName", "-Age").print("LastName Ascending, FirstName Ascending, Age Descending"); arrObj.sortBy("-FirstName", "Age").print("FirstName Descending, Age Ascending"); arrObj.sortBy("-Age").print("Age Descending"); 

Secondo il tuo esempio, devi ordinare per due campi (cognome, nome), piuttosto che uno. È ansible utilizzare la libreria Alasql per rendere questo tipo in una riga:

 var res = alasql('SELECT * FROM ? ORDER BY last_nom, first_nom',[objs]); 

Prova questo esempio su jsFiddle .

ulteriori parametri di desc per il codice Ege Özcan

 function dynamicSort(property, desc) { if (desc) { return function (a, b) { return (a[property] > b[property]) ? -1 : (a[property] < b[property]) ? 1 : 0; } } return function (a, b) { return (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0; } } 

Un’altra opzione:

 var someArray = [...]; function generateSortFn(prop, reverse) { return function (a, b) { if (a[prop] < b[prop]) return reverse ? 1 : -1; if (a[prop] > b[prop]) return reverse ? -1 : 1; return 0; }; } someArray.sort(generateSortFn('name', true)); 

ordina in ordine crescente.

Potrebbe essere necessario convertirli in minuscolo per evitare confusione.

 objs.sort(function (a,b) { var nameA=a.last_nom.toLowerCase(), nameB=b.last_nom.toLowerCase() if (nameA < nameB) return -1; if (nameA > nameB) return 1; return 0; //no sorting }) 
 function compare(propName) { return function(a,b) { if (a[propName] < b[propName]) return -1; if (a[propName] > b[propName]) return 1; return 0; }; } objs.sort(compare("last_nom")); 
 objs.sort(function(a,b){return b.last_nom>a.last_nom}) 

A partire dal 2018 c’è una soluzione molto più breve ed elegante. Basta usare Array.prototype.sort () .

Esempio:

 var items = [ { name: 'Edward', value: 21 }, { name: 'Sharpe', value: 37 }, { name: 'And', value: 45 }, { name: 'The', value: -12 }, { name: 'Magnetic', value: 13 }, { name: 'Zeros', value: 37 } ]; // sort by value items.sort(function (a, b) { return a.value - b.value; }); 

This is a simple problem, don’t know why people have such complex solution.
A simple sort function (based on quick-sort algorithm):

 function sortObjectsArray(objectsArray, sortKey) { // Quick Sort: var retVal; if (1 < objectsArray.length) { var pivotIndex = Math.floor((objectsArray.length - 1) / 2); // middle index var pivotItem = objectsArray[pivotIndex]; // value in the middle index var less = [], more = []; objectsArray.splice(pivotIndex, 1); // remove the item in the pivot position objectsArray.forEach(function(value, index, array) { value[sortKey] <= pivotItem[sortKey] ? // compare the 'sortKey' proiperty less.push(value) : more.push(value) ; }); retVal = sortObjectsArray(less, sortKey).concat([pivotItem], sortObjectsArray(more, sortKey)); } else { retVal = objectsArray; } return retVal; } 

Use example:

 var myArr = [ { val: 'x', idx: 3 }, { val: 'y', idx: 2 }, { val: 'z', idx: 5 }, ]; myArr = sortObjectsArray(myArr, 'idx'); 

Using Ramda,

npm install ramda

 import R from 'ramda' var objs = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ]; var ascendingSortedObjs = R.sortBy(R.prop('last_nom'), objs) var descendingSortedObjs = R.reverse(ascendingSortedObjs) 

I haven’t seen this particular approach suggested, so here’s a terse comparison method I like to use that works for both string and number :

 const objs = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ]; const sortBy = fn => (a, b) => -(fn(a) < fn(b)) || +(fn(a) > fn(b)) const getLastName = o => o.last_nom const sortByLastName = sortBy(getLastName) objs.sort(sortByLastName) console.log(objs.map(getLastName)) 

I Just enhanced Ege Özcan ‘s dynamic sort to dive deep inside objects. If Data looks like this:

 obj = [ { a: { a: 1, b: 2, c: 3 }, b: { a: 4, b: 5, c: 6 } }, { a: { a: 3, b: 2, c: 1 }, b: { a: 6, b: 5, c: 4 } }]; 

and if you want to sort it over aa property I think my enhancement helps very well. I add new functionality to objects like this:

 Object.defineProperty(Object.prototype, 'deepVal', { enumerable: false, writable: true, value: function (propertyChain) { var levels = propertyChain.split('.'); parent = this; for (var i = 0; i < levels.length; i++) { if (!parent[levels[i]]) return undefined; parent = parent[levels[i]]; } return parent; } }); 

and changed _dynamicSort 's return function:

 return function (a,b) { var result = ((a.deepVal(property) > b.deepVal(property)) - (a.deepVal(property) < b.deepVal(property))); return result * sortOrder; } 

And now you can sort by aa this way:

 obj.sortBy('a.a'); 

See Commplete script in JSFiddle

Given the original example:

 var objs = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ]; 

Sort by multiple fields:

 objs.sort(function(left, right) { var last_nom_order = left.last_nom.localeCompare(right.last_nom); var first_nom_order = left.first_nom.localeCompare(right.first_nom); return last_nom_order || first_nom_order; }); 

Gli appunti

  • a.localeCompare(b) is universally supported and returns -1,0,1 if a , a==b , a>b respectively.
  • || in the last line gives last_nom priority over first_nom .
  • Subtraction works on numeric fields: var age_order = left.age - right.age;
  • Negate to reverse order, return -last_nom_order || -first_nom_order || -age_order;

Using xPrototype : https://github.com/reduardo7/xPrototype/blob/master/README.md#sortbycol1-col2-coln

 var o = [ { Name: 'Lazslo', LastName: 'Jamf' }, { Name: 'Pig', LastName: 'Bodine' }, { Name: 'Pirate', LastName: 'Prentice' }, { Name: 'Pag', LastName: 'Bodine' } ]; // Original o.each(function (a, b) { console.log(a, b); }); /* 0 Object {Name: "Lazslo", LastName: "Jamf"} 1 Object {Name: "Pig", LastName: "Bodine"} 2 Object {Name: "Pirate", LastName: "Prentice"} 3 Object {Name: "Pag", LastName: "Bodine"} */ // Sort By LastName ASC, Name ASC o.sortBy('LastName', 'Name').each(function(a, b) { console.log(a, b); }); /* 0 Object {Name: "Pag", LastName: "Bodine"} 1 Object {Name: "Pig", LastName: "Bodine"} 2 Object {Name: "Lazslo", LastName: "Jamf"} 3 Object {Name: "Pirate", LastName: "Prentice"} */ // Sort by LastName ASC and Name ASC o.sortBy('LastName'.asc, 'Name'.asc).each(function(a, b) { console.log(a, b); }); /* 0 Object {Name: "Pag", LastName: "Bodine"} 1 Object {Name: "Pig", LastName: "Bodine"} 2 Object {Name: "Lazslo", LastName: "Jamf"} 3 Object {Name: "Pirate", LastName: "Prentice"} */ // Sort by LastName DESC and Name DESC o.sortBy('LastName'.desc, 'Name'.desc).each(function(a, b) { console.log(a, b); }); /* 0 Object {Name: "Pirate", LastName: "Prentice"} 1 Object {Name: "Lazslo", LastName: "Jamf"} 2 Object {Name: "Pig", LastName: "Bodine"} 3 Object {Name: "Pag", LastName: "Bodine"} */ // Sort by LastName DESC and Name ASC o.sortBy('LastName'.desc, 'Name'.asc).each(function(a, b) { console.log(a, b); }); /* 0 Object {Name: "Pirate", LastName: "Prentice"} 1 Object {Name: "Lazslo", LastName: "Jamf"} 2 Object {Name: "Pag", LastName: "Bodine"} 3 Object {Name: "Pig", LastName: "Bodine"} */ 

I came into problem of sorting array of objects, with changing priority of values, basically I want to sort array of peoples by their Age, and then by surname – or just by surname, name. I think that this is most simple solution compared to another answers.

it’ is used by calling sortPeoples([‘array’, ‘of’, ‘properties’], reverse=false)

 ///////////////////////example array of peoples /////////////////////// var peoples = [ {name: "Zach", surname: "Emergency", age: 1}, {name: "Nancy", surname: "Nurse", age: 1}, {name: "Ethel", surname: "Emergency", age: 1}, {name: "Nina", surname: "Nurse", age: 42}, {name: "Anthony", surname: "Emergency", age: 42}, {name: "Nina", surname: "Nurse", age: 32}, {name: "Ed", surname: "Emergency", age: 28}, {name: "Peter", surname: "Physician", age: 58}, {name: "Al", surname: "Emergency", age: 58}, {name: "Ruth", surname: "Registration", age: 62}, {name: "Ed", surname: "Emergency", age: 38}, {name: "Tammy", surname: "Triage", age: 29}, {name: "Alan", surname: "Emergency", age: 60}, {name: "Nina", surname: "Nurse", age: 58} ]; //////////////////////// Sorting function ///////////////////// function sortPeoples(propertyArr, reverse) { function compare(a,b) { var i=0; while (propertyArr[i]) { if (a[propertyArr[i]] < b[propertyArr[i]]) return -1; if (a[propertyArr[i]] > b[propertyArr[i]]) return 1; i++; } return 0; } peoples.sort(compare); if (reverse){ peoples.reverse(); } }; ////////////////end of sorting method/////////////// function printPeoples(){ $('#output').html(''); peoples.forEach( function(person){ $('#output').append(person.surname+" "+person.name+" "+person.age+"
"); } ) }