J'ai un tableau d'objets JavaScript:
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
Comment puis-je les trier par la valeur de last_nom
en JavaScript?
Je sais sort(a,b)
, mais cela ne semble fonctionner que sur les chaînes et les nombres. Dois-je ajouter une toString()
méthode à mes objets?
javascript
arrays
sorting
Tyrone Slothrop
la source
la source
Réponses:
Il est assez facile d'écrire votre propre fonction de comparaison:
Ou en ligne (c / o Marco Demaio):
la source
return a.last_nom.localeCompare(b.last_nom)
fonctionnera aussi.return a.value - b.value;
(ASC)localeCompare
est important lors de l'utilisation de caractères accentués dans des langues étrangères, et plus élégant également.Vous pouvez également créer une fonction de tri dynamique qui trie les objets en fonction de leur valeur que vous transmettez:
Vous pouvez donc avoir un tableau d'objets comme celui-ci:
... et cela fonctionnera lorsque vous:
En fait, cela répond déjà à la question. La partie ci-dessous est écrite parce que de nombreuses personnes m'ont contacté, se plaignant du fait que cela ne fonctionne pas avec plusieurs paramètres .
Paramètres multiples
Vous pouvez utiliser la fonction ci-dessous pour générer des fonctions de tri avec plusieurs paramètres de tri.
Ce qui vous permettrait de faire quelque chose comme ça:
Tableau de sous-classement
Pour les plus chanceux d'entre nous qui peuvent utiliser ES6, ce qui permet d'étendre les objets natifs:
Cela permettrait ceci:
la source
dynamicSort()
exemple ci-dessus placera les majuscules avant les minuscules. Par exemple, si je les valeursAPd
,Aklin
, etAbe
- les résultats dans un ASC devrait être une sorteAbe
,Aklin
,APd
. Mais avec votre exemple, les résultats sontAPd
,Abe
,Aklin
. Quoi qu'il en soit pour corriger ce comportement?var result = a[property].localeCompare(b[property]);
place devar result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
.if( !isNaN(a[property]) ) a[property] = Number(a[property]); if( !isNaN(b[property]) ) b[property] = Number(b[property]);
Dans ES6 / ES2015 ou version ultérieure, vous pouvez procéder comme suit:
Avant ES6 / ES2015
la source
last_nom
utiliser uniquement le nombre dans le tableau1
:?objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom, undefined, {numberic: true}));
underscore.js
utilisez le soulignement, c'est petit et génial ...
la source
var sortedObjs = _.sortBy( objs, 'first_nom' );
. neobjs
sera pas trié lui-même en conséquence. La fonction renverra un tableau trié. Cela le rendrait plus explicite.var reverseSortedObjs = _.sortBy( objs, 'first_nom' ).reverse();
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"> </script>
Lodash
pour ceux qui préfèrent celui-civar sortedObjs = _.sortBy( objs, 'first_nom' );
ou si vous le souhaitez dans un ordre différent:var sortedObjs = _.orderBy( objs, ['first_nom'],['dsc'] );
Ne comprenez pas pourquoi les gens compliquent les choses:
Pour les moteurs plus stricts:
Échangez l'opérateur pour le trier par ordre alphabétique inverse.
la source
if(a.count == b.count) return a.name > b.name; else return a.count > b.count;
Si vous avez des noms de famille en double, vous pouvez les trier par prénom -
la source
b
devrait venir aprèsa
dans le tableau. Si un nombre positif est retourné, cela signifiea
devrait venir aprèsb
. Si0
est retourné, cela signifie qu'ils sont considérés comme égaux. Vous pouvez toujours lire la documentation: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…1, 0, -1
avant de poser cette question ici. Je ne trouvais tout simplement pas les informations dont j'avais besoin.Solution simple et rapide à ce problème en utilisant l'héritage de prototype:
Exemple / utilisation
Mise à jour: ne modifie plus la baie d'origine.
la source
À partir de 2018, il existe une solution beaucoup plus courte et élégante. Utilisez simplement. Array.prototype.sort () .
Exemple:
la source
a.value - b.value
outil utilisé pour comparer les attributs de l'objet (les nombres dans ce cas) peut être adopté pour les différentes durées des données. Par exemple, l'expression régulière peut être utilisée pour comparer chaque paire de chaînes voisines .Ancienne réponse incorrecte:
MISE À JOUR
Du commentaire de Beauchamp:
Format plus lisible:
Sans ternaires imbriqués:
Explication:
Number()
lanceratrue
vers1
etfalse
vers0
.la source
arr.sort((a, b) => a.name < b.name ? -1 : (a.name > b.name ? 1 : 0))
Au lieu d'utiliser une fonction de comparaison personnalisée, vous pouvez également créer un type d'objet avec une
toString()
méthode personnalisée (qui est invoquée par la fonction de comparaison par défaut):la source
Lodash.js (surensemble de Underscore.js )
Il est bon de ne pas ajouter de cadre pour chaque élément logique simple, mais s'appuyer sur des cadres d'utilitaires bien testés peut accélérer le développement et réduire la quantité de bogues.
Lodash produit du code très propre et favorise une programmation plus fonctionnelle style de . En un coup d'œil, il devient clair quelle est l'intention du code.
Le problème de l'OP peut simplement être résolu comme suit:
Plus d'informations? Par exemple, nous avons l'objet imbriqué suivant:
Nous pouvons maintenant utiliser le raccourci _.property
user.age
pour spécifier le chemin d'accès à la propriété qui doit correspondre. Nous allons trier les objets utilisateur par la propriété d'âge imbriquée. Oui, il permet la correspondance des propriétés imbriquées!Vous voulez qu'il soit inversé? Aucun problème. Utilisez _.reverse .
Vous voulez combiner les deux à l'aide d'une chaîne ?
Ou quand préférez-vous couler sur la chaîne
la source
Vous pouvez utiliser
Moyen le plus simple : Lodash
( https://lodash.com/docs/4.17.10#orderBy )
Cette méthode est similaire à _.sortBy sauf qu'elle permet de spécifier les ordres de tri des itérés par lesquels trier. Si les commandes ne sont pas spécifiées, toutes les valeurs sont triées par ordre croissant. Sinon, spécifiez un ordre de "desc" pour décroissant ou "asc" pour ordre de tri croissant des valeurs correspondantes.
Arguments
collection (Array | Object): collection sur laquelle itérer. [iteratees = [_. identity]] (Array [] | Function [] | Object [] | string []): Les itérés à trier. [commandes] (chaîne []): les ordres de tri des itérés.
Retour
(Array): renvoie le nouveau tableau trié.
la source
Il y a beaucoup de bonnes réponses ici, mais je voudrais souligner qu'elles peuvent être étendues très simplement pour obtenir un tri beaucoup plus complexe. La seule chose que vous devez faire est d'utiliser l'opérateur OR pour chaîner des fonctions de comparaison comme ceci:
Où
fn1
,fn2
... sont les fonctions de tri qui de retour [-1,0,1]. Il en résulte «tri par fn1», «tri par fn2» qui est à peu près égal à ORDER BY en SQL.Cette solution est basée sur le comportement de l'
||
opérateur qui évalue la première expression évaluée qui peut être convertie en true .La forme la plus simple n'a qu'une seule fonction en ligne comme celle-ci:
Ayant deux étapes avec
last_nom
, l'first_nom
ordre de tri ressemblerait à ceci:Une fonction de comparaison générique pourrait ressembler à ceci:
Cette fonction pourrait être étendue pour prendre en charge les champs numériques, la sensibilité à la casse, les types de données arbitraires, etc.
Vous pouvez les utiliser en les enchaînant par priorité de tri:
Le point ici est que le JavaScript pur avec une approche fonctionnelle peut vous mener loin sans bibliothèques externes ou code complexe. Il est également très efficace, car aucune analyse de chaîne ne doit être effectuée
la source
Exemple d'utilisation:
Scénario:
la source
1, 0, -1
sont utilisés pour le tri. Même avec votre explication ci-dessus, qui semble très bonne - je ne comprends toujours pas très bien. Je pense toujours-1
à l'utilisation de la propriété de longueur de tableau, c'est-à-dire:arr.length = -1
signifie que l'élément n'est pas trouvé. Je mélange probablement les choses ici, mais pourriez-vous m'aider à comprendre pourquoi les chiffres1, 0, -1
sont utilisés pour déterminer l'ordre? Merci.a
etb
, sia
est supérieur àb
ajouter 1 à l'index dea
et le placer derrièreb
, sia
est inférieur àb
, soustrayez 1 dea
et placez-le devantb
. Sia
etb
sont identiques, ajoutez 0 àa
et laissez-le où il est.Je n'ai pas vu cette approche particulière suggérée, alors voici une méthode de comparaison laconique que j'aime utiliser qui fonctionne pour les deux
string
etnumber
:Voici une explication de
sortBy()
:sortBy()
accepte unfn
qui sélectionne la valeur d'un objet à utiliser comme comparaison et renvoie une fonction qui peut être transmise directement àArray.prototype.sort()
. Dans cet exemple, nous utilisonso.last_nom
comme valeur de comparaison, donc à chaque fois que nous recevons deux objets,Array.prototype.sort()
tels queet
nous utilisons
pour les comparer.
En se souvenant de cela
fn = o => o.last_nom
, nous pouvons étendre la fonction de comparaison à l'équivalentL'
||
opérateur logique OU possède une fonctionnalité de court-circuit qui est très utile ici. En raison de son fonctionnement, le corps de la fonction ci-dessus signifieEn prime, voici l'équivalent dans ECMAScript 5 sans fonctions fléchées, qui est malheureusement plus détaillé:
la source
Je sais que cette question est trop ancienne, mais je n'ai vu aucune implémentation similaire à la mienne.
Cette version est basée sur l' idiome de transformation schwartzienne .
Voici un exemple d'utilisation:
la source
Tri (plus) Tableaux complexes d'objets
Comme vous rencontrez probablement des structures de données plus complexes comme ce tableau, j'élargirais la solution.
TL; DR
Problème
J'ai rencontré ce qui suit et je n'ai pas pu le changer. Je ne voulais pas non plus aplatir temporairement l'objet. Je ne voulais pas non plus utiliser le soulignement / lodash, principalement pour des raisons de performances et pour le plaisir de l'implémenter moi-même.
Objectif
Le but est de le trier principalement par
People.Name.name
et secondairement parPeople.Name.surname
Obstacles
Maintenant, dans la solution de base, utilise la notation entre crochets pour calculer les propriétés à trier dynamiquement. Ici, cependant, nous devons également construire dynamiquement la notation des crochets, car vous vous attendez à ce que certains
People['Name.name']
fonctionnent - ce qui ne fonctionne pas.Le simple fait
People['Name']['name']
, en revanche, est statique et vous permet uniquement de descendre le n niveau -ème.Solution
Le principal ajout ici sera de parcourir l'arborescence des objets et de déterminer la valeur de la dernière feuille, vous devez spécifier, ainsi que toute feuille intermédiaire.
Exemple
Exemple de travail sur JSBin
la source
Encore une option:
tri croissant par défaut.
la source
Une fonction simple qui trie un tableau d'objets par une propriété
Usage:
la source
Un moyen simple:
Voir cela
'.toLowerCase()'
est nécessaire pour éviter les erreurs dans la comparaison des chaînes.la source
objs.sort( (a,b) => b.last_nom.toLowerCase() < a.last_nom.toLowerCase() );
paramètres de desc supplémentaires pour le code Ege Özcan
la source
En combinant la solution dynamique d'Ege avec l'idée de Vinay, vous obtenez une belle solution robuste:
Usage:
la source
Selon votre exemple, vous devez trier par deux champs (nom, prénom), plutôt qu'un. Vous pouvez utiliser la bibliothèque Alasql pour effectuer ce tri sur une seule ligne:
Essayez cet exemple sur jsFiddle .
la source
la source
Étant donné l'exemple d'origine:
Trier par plusieurs champs:
Remarques
a.localeCompare(b)
est universellement supporté et retourne -1,0,1 sia<b
,a==b
,a>b
respectivement.||
dans la dernière ligne donne lalast_nom
priorité surfirst_nom
.var age_order = left.age - right.age;
return -last_nom_order || -first_nom_order || -age_order;
la source
Essaye ça,
la source
Vous devrez peut-être les convertir en minuscules afin d'éviter toute confusion.
la source
la source
Avec Ramda,
npm install ramda
la source
C'est un problème simple, je ne sais pas pourquoi les gens ont une solution aussi complexe.
Une fonction de tri simple (basée sur l' algorithme de tri rapide):
Exemple d'utilisation:
la source