Aucune de ces réponses n'est idéale comme méthode à usage général pour utiliser plusieurs champs dans un tri. Toutes les approches ci-dessus sont inefficaces car elles nécessitent soit de trier le tableau plusieurs fois (ce qui, sur une liste suffisamment grande, pourrait ralentir beaucoup les choses), soit elles génèrent d'énormes quantités d'objets de déchets que la machine virtuelle devra nettoyer (et finalement ralentir le programme vers le bas).
Voici une solution rapide, efficace, permettant facilement le tri inversé et pouvant être utilisée avec underscore
oulodash
, ou directement avecArray.sort
La partie la plus importante est la compositeComparator
méthode, qui prend un tableau de fonctions de comparaison et renvoie une nouvelle fonction de comparateur composite.
/**
* 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);
});
}
Vous aurez également besoin d'une fonction de comparaison pour comparer les champs sur lesquels vous souhaitez trier. La naturalSort
fonction créera un comparateur à partir d'un champ particulier. Ecrire un comparateur pour le tri inversé est également trivial.
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;
}
}
(Tout le code jusqu'à présent est réutilisable et pourrait être conservé dans le module utilitaire, par exemple)
Ensuite, vous devez créer le comparateur composite. Pour notre exemple, cela ressemblerait à ceci:
var cmp = compositeComparator([naturalSort('roomNumber'), naturalSort('name')]);
Cela triera par numéro de chambre, suivi du nom. L'ajout de critères de tri supplémentaires est simple et n'affecte pas les performances du tri.
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);
Renvoie ce qui suit
[ { name: 'Chris', roomNumber: 1, bedNumber: 1 },
{ name: 'Lisa', roomNumber: 2, bedNumber: 2 },
{ name: 'Omar', roomNumber: 2, bedNumber: 1 },
{ name: 'John', roomNumber: 3, bedNumber: 1 } ]
La raison pour laquelle je préfère cette méthode est qu'elle permet un tri rapide sur un nombre arbitraire de champs, ne génère pas beaucoup de déchets ou n'effectue pas de concaténation de chaînes à l'intérieur du tri et peut facilement être utilisée pour que certaines colonnes soient triées à l'envers tandis que les colonnes d'ordre utilisent naturel Trier.