Nessuna di queste risposte è ideale come metodo generico per l'utilizzo di più campi in un ordinamento. Tutti gli approcci di cui sopra sono inefficienti in quanto richiedono l'ordinamento dell'array più volte (il che, su un elenco abbastanza ampio potrebbe rallentare molto) o generano enormi quantità di oggetti spazzatura che la VM dovrà pulire (e alla fine rallentando il programma inattivo).
Ecco una soluzione veloce, efficiente, che consente facilmente lo smistamento inverso e può essere utilizzata con underscoreo lodash, o direttamente conArray.sort
La parte più importante è il compositeComparatormetodo, che accetta un array di funzioni di confronto e restituisce una nuova funzione di confronto composto.
/**
* Chains a comparator function to another comparator
* and returns the result of the first comparator, unless
* the first comparator returns 0, in which case the
* result of the second comparator is used.
*/
function makeChainedComparator(first, next) {
return function(a, b) {
var result = first(a, b);
if (result !== 0) return result;
return next(a, b);
}
}
/**
* Given an array of comparators, returns a new comparator with
* descending priority such that
* the next comparator will only be used if the precending on returned
* 0 (ie, found the two objects to be equal)
*
* Allows multiple sorts to be used simply. For example,
* sort by column a, then sort by column b, then sort by column c
*/
function compositeComparator(comparators) {
return comparators.reduceRight(function(memo, comparator) {
return makeChainedComparator(comparator, memo);
});
}
Avrai anche bisogno di una funzione di confronto per confrontare i campi su cui desideri ordinare. La naturalSortfunzione creerà un comparatore dato un particolare campo. Anche la scrittura di un comparatore per l'ordinamento inverso è banale.
function naturalSort(field) {
return function(a, b) {
var c1 = a[field];
var c2 = b[field];
if (c1 > c2) return 1;
if (c1 < c2) return -1;
return 0;
}
}
(Tutto il codice fino ad ora è riutilizzabile e potrebbe essere mantenuto nel modulo di utilità, per esempio)
Successivamente, è necessario creare il comparatore composito. Per il nostro esempio, sarebbe simile a questo:
var cmp = compositeComparator([naturalSort('roomNumber'), naturalSort('name')]);
Questo ordinerà per numero di stanza, seguito dal nome. L'aggiunta di ulteriori criteri di ordinamento è banale e non influisce sulle prestazioni dell'ordinamento.
var patients = [
{name: 'John', roomNumber: 3, bedNumber: 1},
{name: 'Omar', roomNumber: 2, bedNumber: 1},
{name: 'Lisa', roomNumber: 2, bedNumber: 2},
{name: 'Chris', roomNumber: 1, bedNumber: 1},
];
// Sort using the composite
patients.sort(cmp);
console.log(patients);
Restituisce quanto segue
[ { name: 'Chris', roomNumber: 1, bedNumber: 1 },
{ name: 'Lisa', roomNumber: 2, bedNumber: 2 },
{ name: 'Omar', roomNumber: 2, bedNumber: 1 },
{ name: 'John', roomNumber: 3, bedNumber: 1 } ]
Il motivo per cui preferisco questo metodo è che consente l'ordinamento rapido su un numero arbitrario di campi, non genera molta spazzatura o esegue la concatenazione di stringhe all'interno dell'ordinamento e può essere facilmente utilizzato in modo che alcune colonne siano ordinate al contrario mentre le colonne dell'ordine usano il naturale ordinare.