J'essaye de trier un tableau avec des objets basés sur plusieurs attributs. C'est-à-dire que si le premier attribut est le même entre deux objets, un deuxième attribut doit être utilisé pour comparer les deux objets. Par exemple, considérez le tableau suivant:
var patients = [
[{name: 'John', roomNumber: 1, bedNumber: 1}],
[{name: 'Lisa', roomNumber: 1, bedNumber: 2}],
[{name: 'Chris', roomNumber: 2, bedNumber: 1}],
[{name: 'Omar', roomNumber: 3, bedNumber: 1}]
];
En les triant par l' roomNumber
attribut, j'utiliserais le code suivant:
var sortedArray = _.sortBy(patients, function(patient) {
return patient[0].roomNumber;
});
Cela fonctionne bien, mais comment dois-je procéder pour que «John» et «Lisa» soient triés correctement?
la source
[0]
indexeur est requis car dans l'exemple d'origine,patients
est un tableau de tableaux. C'est aussi pourquoi la «solution plus simple» dans le billet de blog mentionné dans un autre commentaire ne fonctionnera pas ici.Voici une astuce hacky que j'utilise parfois dans ces cas: combinez les propriétés de manière à ce que le résultat soit triable:
Cependant, comme je l'ai dit, c'est assez hacky. Pour faire cela correctement, vous voudrez probablement utiliser la
sort
méthode JavaScript principale :Bien sûr, cela triera votre tableau en place. Si vous voulez une copie triée (comme
_.sortBy
vous le donnez), clonez d'abord le tableau:Par ennui, je viens d'écrire une solution générale (pour trier par un nombre arbitraire de clés) pour cela aussi: jetez un œil .
la source
return [patient[0].roomNumber, patient[0].name];
pas sans lejoin
?compare
valeurs de poignée qui ne sont pas des valeurs primitives -undefined
,null
ou des objets simples?Je sais que je suis en retard à la fête, mais je voulais ajouter ceci pour ceux qui ont besoin d'une solution plus propre et plus rapide que ceux déjà suggérés. Vous pouvez chaîner les appels sortBy par ordre de propriété la moins importante à la propriété la plus importante. Dans le code ci-dessous, je crée un nouveau tableau de patients triés par nom dans RoomNumber à partir du tableau d'origine appelé patients .
la source
btw votre initialiseur pour les patients est un peu bizarre, n'est-ce pas? pourquoi ne pas initialiser cette variable comme ceci - comme un vrai tableau d'objets - vous pouvez le faire en utilisant _.flatten () et non comme un tableau de tableaux d'un seul objet, c'est peut-être un problème de faute de frappe):
J'ai trié la liste différemment et ajouté Kiko dans le lit de Lisa; juste pour le plaisir et voir quels changements seraient apportés ...
inspecter trié et vous verrez ceci
donc ma réponse est: utilisez un tableau dans votre fonction de rappel, c'est assez similaire à la réponse de Dan Tao , j'oublie juste la jointure (peut-être parce que j'ai supprimé le tableau de tableaux de l'élément unique :))
En utilisant votre structure de données, alors il serait :
et un testload serait intéressant ...
la source
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.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.(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:
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.
Renvoie ce qui suit
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.
la source
Exemple simple de http://janetriley.net/2014/12/sort-on-multiple-keys-with-underscores-sortby.html (avec la permission de @MikeDevenney)
Code
Avec vos données
la source
Peut-être que le fichier underscore.js ou simplement les moteurs Javascript sont différents maintenant que lorsque ces réponses ont été écrites, mais j'ai pu résoudre ce problème en renvoyant simplement un tableau des clés de tri.
En action, veuillez voir ce violon: https://jsfiddle.net/mikeular/xenu3u91/
la source
Renvoyez simplement un tableau de propriétés avec lesquelles vous souhaitez trier:
Syntaxe ES6
Syntaxe ES5
Cela n'a aucun effet secondaire de la conversion d'un nombre en chaîne.
la source
Vous pouvez concaténer les propriétés par lesquelles vous souhaitez trier dans l'itérateur:
ou quelque chose d'équivalent.
REMARQUE: Puisque vous convertissez l'attribut numérique roomNumber en chaîne, vous devrez faire quelque chose si vous aviez des numéros de pièce> 10. Sinon, 11 viendra avant 2. Vous pouvez compléter avec des zéros non significatifs pour résoudre le problème, c'est-à-dire 01 au lieu de 1.
la source
Je pense que vous feriez mieux d'utiliser
_.orderBy
au lieu desortBy
:la source
_.orderBy
fonctionne, mais c'est une méthode de la bibliothèque lodash, et non un tiret bas: lodash.com/docs/4.17.4#orderBy lodash est principalement un remplacement instantané du trait de soulignement, donc il pourrait être approprié pour l'OP.Si vous utilisez Angular, vous pouvez utiliser son filtre numérique dans le fichier html plutôt que d'ajouter des gestionnaires JS ou CSS. Par exemple:
Dans cet exemple, si val = 1234567, il sera affiché comme
Exemple et conseils supplémentaires sur: https://docs.angularjs.org/api/ng/filter/number
la source