Trier le tableau par prénom (alphabétiquement) en Javascript

647

J'ai obtenu un tableau (voir ci-dessous pour un objet dans le tableau) que je dois trier par prénom en utilisant JavaScript. Comment puis-je le faire?

var user = {
   bio: null,
   email:  "[email protected]",
   firstname: "Anna",
   id: 318,
   lastAvatar: null,
   lastMessage: null,
   lastname: "Nickson",
   nickname: "anny"
};
Jonathan Clark
la source
duplication possible du tableau
Felix Kling

Réponses:

1068

Supposons que vous ayez un tableau users. Vous pouvez utiliser users.sortet passer une fonction qui prend deux arguments et les comparer (comparateur)

Il devrait revenir

  • quelque chose de négatif si le premier argument est inférieur au second (doit être placé avant le second dans le tableau résultant)
  • quelque chose de positif si le premier argument est plus grand (doit être placé après le deuxième)
  • 0 si ces deux éléments sont égaux.

Dans notre cas, si deux éléments sont aet bnous voulons comparer a.firstnameetb.firstname

Exemple:

users.sort(function(a, b){
    if(a.firstname < b.firstname) { return -1; }
    if(a.firstname > b.firstname) { return 1; }
    return 0;
})

Ce code va fonctionner avec n'importe quel type.

Notez que dans la "vraie vie" ™, vous voulez souvent ignorer la casse, trier correctement les signes diacritiques, les symboles étranges comme ß, etc. lorsque vous comparez des chaînes, vous pouvez donc les utiliser localeCompare. Voir les autres réponses pour plus de clarté.

RiaD
la source
5
Friggin génial ... Je trie une liste de nodosités par id ... fonctionne comme un charme. Thx une tonne!
Cody
74
Pour ceux qui arriveront à une date ultérieure, la réponse de Mrchief est meilleure car elle n'est pas sensible à la casse.
mlienau
25
@mlienau, je n'appellerais pas ça mieux ou pire. C'est juste un autre
RiaD
19
@RiaD assez juste. Je ne peux pas penser à de nombreux cas de tri alphabétique des éléments, y compris la casse, où «Zebra» apparaît dans la liste avant «pomme», serait très utile.
mlienau
15
Ce code ne fonctionnera que sur les pays anglophones. Dans d'autres pays, vous devriez utiliser la réponse de l'ovunccétine aveclocaleCompare .
Spoike
546

Code le plus court possible avec ES6!

users.sort((a, b) => a.firstname.localeCompare(b.firstname))

Le support de base de String.prototype.localeCompare () est universel!

Nachiketha
la source
27
De loin la meilleure réponse si vous vivez en 2017
nathanbirrell
52
Meilleure réponse aussi si vous vivez en 2018;)
Simone
49
Ce sera probablement la meilleure réponse pour 2019 aussi.
Ahmad Maleki
24
2020 peut-être? ou naaa?
kspearrin
15
ah mec, en 2030 la terre inonde et cela ne fonctionne que dans les montagnes.
Starfs
343

Quelque chose comme ça:

array.sort(function(a, b){
 var nameA=a.name.toLowerCase(), nameB=b.name.toLowerCase();
 if (nameA < nameB) //sort string ascending
  return -1;
 if (nameA > nameB)
  return 1;
 return 0; //default return value (no sorting)
});
Mrchief
la source
43
Lorsque le tri des chaînes «toLowerCase ()» est très important - les majuscules peuvent affecter votre tri.
MarzSocks
3
Au cas où quelqu'un d'autre se demanderait quels sont les impacts de toLowerCase, ce n'est pas grand-chose:'a'>'A' //true 'z'>'a' //true 'A'>'z' //false
SimplGy
14
@SimplGy Je dirais que son impact est un peu plus important que ce que vous lui attribuez. Par exemple, comme indiqué dans les commentaires de la réponse acceptée, il est important de savoir si votre fonction de tri triera la chaîne 'Zebra'plus haut que la chaîne 'apple', ce qu'elle fera si vous n'utilisez pas le .toLowerCase().
PrinceTyke
1
@PrinceTyke ouais c'est un bon homme de cas. 'Z' < 'a' // trueet'z' < 'a' // false
SimplGy
2
Tous les points valides et je dirais que le tri est toujours un genre de "ça dépend". Si vous triez par nom, la sensibilité à la casse peut ne pas avoir d'importance. Dans d'autres cas, c'est possible. Quoi qu'il en soit, je pense que l'adoption de sa situation spécifique n'est pas difficile une fois que vous avez l'idée de base.
Mrchief
336

Si les chaînes comparées contiennent des caractères unicode, vous pouvez utiliser la localeComparefonction de Stringclasse comme suit:

users.sort(function(a,b){
    return a.firstname.localeCompare(b.firstname);
})
ovunccétine
la source
3
String.localeCompare ne prend pas en charge Safari et IE <11 :)
CORSAIR
13
@CORSAIR, il est pris en charge, ce ne sont que les deuxième et troisième paramètres qui ne sont pas pris en charge.
Codler
6
@CORSAIR l'utilisation dans l'exemple est prise en charge dans tous les principaux navigateurs IE: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… . LocaleCompare prend également en compte la capitalisation, donc je pense que cette implémentation devrait être considérée comme la meilleure pratique.
Matt Jensen
9
users.sort ((a, b) => a.firstname.localeCompare (b.firstname)) // Version courte n sweet ES6!
Nachiketha
4
réservoirs bro. en utilisation ES6users.sort((a, b) => a.name.localeCompare(b.name))
Mohmmad Ebrahimi Aval
32

Joli petit ES6 one liner:

users.sort((a, b) => a.firstname !== b.firstname ? a.firstname < b.firstname ? -1 : 1 : 0);
Sam Logan
la source
2
Celui-ci est incomplet car il ne gère pas correctement les valeurs égales.
Karl-Johan Sjögren
1
Bien sûr, merci d'avoir repéré cela, j'ai ajouté une vérification pour les valeurs correspondantes
Sam Logan
pas mal je suppose que si vous voulez vraiment tout sur une seule ligne, les ternaires imbriqués deviennent confus pour la lisibilité
russter
24

Nous pouvons utiliser localeCompare mais devons également vérifier les clés pour les valeurs de falsey

Le code ci-dessous ne fonctionnera pas si une entrée manque lname.

obj.sort((a, b) => a.lname.localeCompare(b.lname))

Nous devons donc vérifier la valeur de falsey comme ci-dessous

let obj=[
{name:'john',lname:'doe',address:'Alaska'},
{name:'tom',lname:'hopes',address:'California'},
{name:'harry',address:'Texas'}
]
let field='lname';
console.log(obj.sort((a, b) => (a[field] || "").toString().localeCompare((b[field] || "").toString())));

OU

nous pouvons utiliser lodash, c'est très simple. Il détectera les valeurs renvoyées, c'est-à-dire s'il s'agit d'un nombre ou d'une chaîne et effectuera le tri en conséquence.

import sortBy from 'lodash/sortBy';
sortBy(obj,'name')

https://lodash.com/docs/4.17.5#sortBy

sumit
la source
2
Lodash est assez soigné! Je n'en avais jamais entendu parler auparavant. Fonctionne très bien!
Derk Jan Speelman
15

underscorejs offre la très belle fonction _.sortBy:

_.sortBy([{a:1},{a:3},{a:2}], "a")

ou vous pouvez utiliser une fonction de tri personnalisée:

_.sortBy([{a:"b"},{a:"c"},{a:"a"}], function(i) {return i.a.toLowerCase()})
Peter T.
la source
2
le deuxième exemple implique le retour de chaînes. Détecte-t-on que sortByles valeurs retournées sont des chaînes et effectue donc un tri alphabétique? Merci
superjos
12

Dans le cas où nous trions des noms ou quelque chose avec des caractères spéciaux, comme ñ ou áéíóú (communs en espagnol), nous pourrions utiliser les paramètres locaux ( es pour l'espagnol dans ce cas) et des options comme celle-ci:

let user = [{'firstname': 'Az'},{'firstname': 'Áb'},{'firstname':'ay'},{'firstname': 'Ña'},{'firstname': 'Nz'},{'firstname': 'ny'}];


user.sort((a, b) => a.firstname.localeCompare(b.firstname, 'es', {sensitivity: 'base'}))


console.log(user)

Les options locales officielles peuvent être trouvées ici en iana , es (espagnol), de (allemand), fr (français). À propos de la base de sensibilité signifie:

Seules les chaînes qui diffèrent en lettres de base se comparent comme inégales. Exemples: a ≠ b, a = á, a = A.

Emeeus
la source
8

Fondamentalement, vous pouvez trier les tableaux avec le tri de méthode, mais si vous voulez trier les objets, vous devez passer une fonction pour trier la méthode du tableau, donc je vais vous donner un exemple en utilisant votre tableau

user = [{
bio: "<null>",
email: "[email protected]",
firstname: 'Anna',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
},
{
bio: "<null>",
email: "[email protected]",
firstname: 'Senad',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
},
{
bio: "<null>",
email: "[email protected]",
firstname: 'Muhamed',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
}];

var ar = user.sort(function(a, b)
{
  var nA = a.firstname.toLowerCase();
  var nB = b.firstname.toLowerCase();

  if(nA < nB)
    return -1;
  else if(nA > nB)
    return 1;
 return 0;
});
Senad Meškin
la source
pourquoi retourner 0 à la fin?
Nobita
=, lorsque les chaînes sont identiques
Senad Meškin
mais dans ce cas, ne devrait-il pas elseêtre supprimé? Sinon, cela return 0ne sera jamais lu
Nobita
2
ce n'est pas "autrement", c'est "sinon si"
Senad Meškin
8

Inspiré de cette réponse,

users.sort((a,b) => (a.firstname  - b.firstname));
Isuru Siriwardana
la source
8

Une notation plus compacte:

user.sort(function(a, b){
    return a.firstname === b.firstname ? 0 : a.firstname < b.firstname ? -1 : 1;
})
James Andrews
la source
il est plus compact mais viole son contrat: sign(f(a, b)) =-sign(f(b, a))(pour a = b)
RiaD
3
le retour a.firstname == b.firstnamedoit être utilisé ===pour être complet
puiu
6

également pour le tri asec et desc, vous pouvez utiliser ceci: supposons que nous ayons une variable SortType qui spécifie le tri croissant ou le tri décroissant que vous souhaitez:

 users.sort(function(a,b){
            return   sortType==="asc"? a.firstName.localeCompare( b.firstName): -( a.firstName.localeCompare(  b.firstName));
        })
ghazaleh javaheri
la source
5

Une fonction généralisée peut être écrite comme ci-dessous

    function getSortedData(data, prop, isAsc) {
        return data.sort((a, b) => (a[prop] < b[prop] ? -1 : 1) * (isAsc ? 1 : -1));
   }

vous pouvez passer les paramètres ci-dessous

  1. Les données que vous souhaitez trier
  2. La propriété dans les données par elle doit être triée
  3. Le dernier paramètre est de type booléen. Il vérifie si vous souhaitez trier par ordre croissant ou décroissant
Santosh
la source
4

essayer

users.sort((a,b)=> (a.firstname>b.firstname)*2-1)

Kamil Kiełczewski
la source
2
la fonction de tri doit renvoyer -1,0,1. celui-ci ne renvoie que -1,1.
Radu Luncasu
@RaduLuncasu - pouvez-vous fournir des données de test (tableau d'utilisateurs) qui montrent que la solution ci-dessus donne un mauvais résultat? (pour autant que je sache, manquer zéro n'est pas un problème)
Kamil Kiełczewski
Si compareFunction (a, b) renvoie 0, laissez a et b inchangés l'un par rapport à l'autre, mais triés par rapport à tous les différents éléments.
Radu Luncasu
@RaduLuncasu ok, mais ces informations ne signifient pas que zéro est obligatoire. La meilleure façon de le montrer est de préparer des données qui ne fonctionnent pas - mais pour autant que je sache que cela est impossible - par exemple[9,8,7,6,5,1,2,3].sort((a,b) => a<b ? -1 : 1)
Kamil Kiełczewski
3

Vous pouvez l'utiliser pour des objets

transform(array: any[], field: string): any[] {
return array.sort((a, b) => a[field].toLowerCase() !== b[field].toLowerCase() ? a[field].toLowerCase() < b[field].toLowerCase() ? -1 : 1 : 0);}
Andre Coetzee
la source
2

en termes simples, vous pouvez utiliser cette méthode

users.sort(function(a,b){return a.firstname < b.firstname ? -1 : 1});
FarukT
la source
1

Vous pouvez utiliser la méthode du tableau intégré - sort. Cette méthode prend une méthode de rappel comme paramètre



    // custom sort function to be passed as param/callback to the Array's sort method
    function myCustomSort(a, b) {
        return (a.toLowerCase() > b.toLowerCase()) ? 1 : -1;
    }

    // Actual method to be called by entity that needs sorting feature
    function sortStrings() {
        var op = Array.prototype.sort.call(arguments, myCustomSort);
    }

    // Testing the implementation
    var sortedArray = sortStrings("Burger", "Mayo1", "Pizza", "boxes", "Apples", "Mayo");
    console.log(sortedArray); //["Apples", "boxes", "Burger", "Mayo", "Mayo1", "Pizza"]


Points clés à noter pour comprendre ce code.

  1. Dans ce cas, la méthode personnalisée myCustomSortdoit renvoyer +1 ou -1 pour chaque comparaison de paires d'éléments (du tableau d'entrée).
  2. Utilisez toLowerCase()/ toUpperCase()dans la méthode de rappel de tri personnalisé afin que la différence de casse n'affecte pas l'exactitude du processus de tri.

J'espère que cette explication est suffisamment claire. N'hésitez pas à commenter si vous le pensez, plus d'informations sont nécessaires.

À votre santé!

shanky
la source
Ce n'est pas une bonne réponse car elle n'effectue que des vérifications inférieures et supérieures aux vérifications et non une vérification égale.
Steel Brain
cela n'apporte pas non plus quelque chose de nouveau à la table, par rapport à l'une des réponses qui s'y trouvent depuis ~ 2011.
amenthes
1

Poussé les meilleures réponses dans un prototype pour trier par clé.

Array.prototype.alphaSortByKey= function (key) {
    this.sort(function (a, b) {
        if (a[key] < b[key])
            return -1;
        if (a[key] > b[key])
            return 1;
        return 0;
    });
    return this;
};
msponagle
la source
0

Vous pouvez utiliser quelque chose de similaire pour vous débarrasser de la casse

users.sort(function(a, b){

  //compare two values
  if(a.firstname.toLowerCase() < b.firstname.toLowerCase()) return -1;
  if(a.firstname.toLowerCase() > b.firstname.toLowerCase()) return 1;
  return 0;

})
SAN_WEB
la source
7
Même réponse que celle de Mrchief. Avec l'inconvénient supplémentaire que le toLowerCase est effectué quatre fois par comparaison au lieu de deux fois.
amenthes
0

Mon implémentation fonctionne très bien dans les anciennes versions ES:

sortObject = function(data) {
    var keys = Object.keys(data);
    var result = {};

    keys.sort();

    for(var i = 0; i < keys.length; i++) {
        var key = keys[i];

        result[key] = data[key];
    }

    return result;
};
extrême
la source
0

Juste pour mémoire, si vous voulez avoir une fonction de tri nommée, la syntaxe est la suivante:

let sortFunction = (a, b) => {
 if(a.firstname < b.firstname) { return -1; }
 if(a.firstname > b.firstname) { return 1; }
 return 0;
})
users.sort(sortFunction)

Notez que ce qui suit ne fonctionne PAS:

users.sort(sortFunction(a,b))
Katinka Hesselink
la source