J'ai une liste d'objets que je souhaite trier en fonction d'un champ attr
de type chaîne. J'ai essayé d'utiliser-
list.sort(function (a, b) {
return a.attr - b.attr
})
mais a constaté que -
cela ne semble pas fonctionner avec les chaînes en JavaScript. Comment puis-je trier une liste d'objets en fonction d'un attribut avec une chaîne de type?
javascript
string
airportyh
la source
la source
JavaScript case insensitive string comparison
sur stackoverflow.com/questions/2140627/…Javascript : remove accents/diacritics in strings
sur stackoverflow.com/questions/990904/…Réponses:
Utilisez
String.prototype.localeCompare
un par votre exemple:Nous forçons a.attr à être une chaîne pour éviter les exceptions.
localeCompare
est pris en charge depuis Internet Explorer 6 et Firefox 1. Vous pouvez également voir le code suivant utilisé qui ne respecte pas les paramètres régionaux:la source
localeCompare()
ne rencontre pas ce problème mais ne comprend pas les chiffres, vous obtiendrez donc ["1", "10", "2"] comme pour les comparaisons de tri dans la plupart des langues. si vous voulez trier votre interface utilisateur, consultez l'algorithme de tri alphanum / naturel stackoverflow.com/questions/4340227/… ou stackoverflow.com/questions/4321829/…localeCompare()
n'est pris en charge que dans les navigateurs modernes: IE11 + au moment de la rédaction, voir developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…localeCompare()
en charge le retour de nombreuses versions, mais ne prend pas en charge la spécification des paramètres régionaux jusqu'à la version 11. Notez également les questions liées à Dead.Rabit.Une réponse mise à jour (octobre 2014)
J'étais vraiment ennuyé par cet ordre de tri naturel des chaînes, j'ai donc pris un certain temps pour enquêter sur ce problème. J'espère que ça aide.
Longue histoire courte
localeCompare()
le support des personnages est dur à cuire, utilisez-le. Comme indiqué parShog9
, la réponse à votre question est:Bogues trouvés dans toutes les implémentations javascript personnalisées "ordre de tri des chaînes naturelles"
Il existe de nombreuses implémentations personnalisées, essayant de faire une comparaison de chaînes plus précisément appelée "ordre de tri des chaînes naturelles"
En "jouant" avec ces implémentations, j'ai toujours remarqué un choix étrange "d'ordre de tri naturel", ou plutôt des erreurs (ou des omissions dans le meilleur des cas).
En règle générale, les caractères spéciaux (espace, tiret, esperluette, crochets, etc.) ne sont pas traités correctement.
Vous les trouverez ensuite apparaissant mélangés à différents endroits, généralement cela pourrait être:
Quand on aurait pu s'attendre à ce que tous les caractères spéciaux soient "regroupés" en un seul endroit, à l'exception peut-être du caractère spécial espace (qui serait toujours le premier caractère). C'est-à-dire, soit tous avant les nombres, soit tous entre les chiffres et les lettres (les minuscules et les majuscules étant «ensemble» l'un après l'autre), ou tous après les lettres.
Ma conclusion est qu'ils ne parviennent pas tous à fournir un ordre cohérent lorsque je commence à ajouter des caractères à peine inhabituels (c'est-à-dire des caractères avec des signes diacritiques ou des caractères tels qu'un tiret, un point d'exclamation, etc.).
Recherche sur les implémentations personnalisées:
Natural Compare Lite
https://github.com/litejs/natural-compare-lite : échoue au tri de manière cohérente https://github.com/litejs/natural-compare-lite/issues/1 et http://jsbin.com/bevututodavi/ 1 / éditer? Js, console , tri de base des caractères latins http://jsbin.com/bevututodavi/5/edit?js,consoleNatural Sort
https://github.com/javve/natural-sort : échoue au tri de manière cohérente, voir le problème https://github.com/javve/natural-sort/issues/7 et voir les caractères latins de base triant http: // jsbin. com / cipimosedoqe / 3 / edit? js, consoleJavascript Natural Sort
https://github.com/overset/javascript-natural-sort : semble plutôt négligé depuis février 2012, échoue au tri de manière cohérente, voir le problème https://github.com/overset/javascript-natural-sort/issues/16Alphanum
http://www.davekoelle.com/files/alphanum.js , échoue au tri de manière cohérente, voir http://jsbin.com/tuminoxifuyo/1/edit?js,consoleImplémentations natives de "l'ordre de tri des chaînes naturelles" des navigateurs via
localeCompare()
localeCompare()
la plus ancienne implémentation (sans les paramètres régionaux et les arguments d'options) est prise en charge par IE6 +, voir http://msdn.microsoft.com/en-us/library/ie/s4esdbwz(v=vs.94).aspx (faites défiler jusqu'à localeCompare ( ) méthode). LalocaleCompare()
méthode intégrée fait un bien meilleur travail de tri, même les caractères internationaux et spéciaux. Le seul problème avec lalocaleCompare()
méthode est que "les paramètres régionaux et l'ordre de tri utilisés dépendent entièrement de l'implémentation". En d'autres termes, lorsque vous utilisez localeCompare tel que stringOne.localeCompare (stringTwo): Firefox, Safari, Chrome et IE ont un ordre de tri différent pour les chaînes.Recherche sur les implémentations natives du navigateur:
Difficulté de "l'ordre de tri naturel des chaînes"
La mise en œuvre d'un algorithme solide (ce qui signifie: cohérent mais couvrant également un large éventail de caractères) est une tâche très difficile. UTF8 contient plus de 2000 caractères et couvre plus de 120 scripts (langues) . Enfin, il existe quelques spécifications pour ces tâches, il est appelé "Algorithme de Collation Unicode", qui peut être trouvé à http://www.unicode.org/reports/tr10/ . Vous pouvez trouver plus d'informations à ce sujet sur cette question que j'ai publiée /software/257286/is-there-any-language-agnostic-specification-for-string-natural-sorting-order
Conclusion finale
Donc, compte tenu du niveau actuel de support fourni par les implémentations personnalisées javascript que j'ai rencontrées, nous ne verrons probablement jamais rien se rapprocher de la prise en charge de tous ces caractères et scripts (langues). Par conséquent, je préfère utiliser la méthode localeCompare () native des navigateurs. Oui, il a l'inconvénient d'être non cohérent entre les navigateurs, mais les tests de base montrent qu'il couvre une gamme beaucoup plus large de caractères, permettant des ordres de tri solides et significatifs.
Donc, comme l'a souligné par
Shog9
, la réponse à votre question est:Lectures complémentaires:
Merci à la gentille réponse de Shog9, qui m'a mis dans la "bonne" direction je crois
la source
Réponse (dans ECMAScript moderne)
Ou
La description
La conversion d'une valeur booléenne en un nombre donne les résultats suivants:
true
->1
false
->0
Considérez trois modèles possibles:
(x > y) - (y < x)
->1 - 0
->1
(x > y) - (y < x)
->0 - 0
->0
(x > y) - (y < x)
->0 - 1
->-1
(Alternative)
+(x > y) || -(x < y)
->1 || 0
->1
+(x > y) || -(x < y)
->0 || 0
->0
+(x > y) || -(x < y)
->0 || -1
->-1
Ces logiques sont donc équivalentes aux fonctions typiques de comparateur de tri.
la source
localeCompare
et la comparaison standard donnent des résultats différents. À quoi vous attendez-vous?["A", "b", "C", "d"].sort((a, b) => a.localeCompare(b))
trie dans l'ordre alphabétique insensible à la casse tandis que le["A", "b", "C", "d"].sort((a, b) => (a > b) - (a < b))
fait dans l'ordre desVous devez utiliser> ou <et == ici. La solution serait donc:
la source
Fonction flèche ternaire imbriquée
la source
puisque les chaînes peuvent être comparées directement en javascript, cela fera le travail
la soustraction dans une fonction de tri n'est utilisée que lorsque le tri non alphabétique (numérique) est souhaité et bien sûr cela ne fonctionne pas avec les chaînes
la source
J'avais été gêné à ce sujet depuis longtemps, alors j'ai finalement fait des recherches et vous donner cette raison de longue haleine pour laquelle les choses sont comme elles sont.
De la spécification :
Alors maintenant, nous passons à 11.9.6
C'est tout. L'opérateur triple égal appliqué aux chaînes renvoie vrai si les arguments sont exactement les mêmes chaînes (même longueur et mêmes caractères aux positions correspondantes).
Cela
===
fonctionnera donc dans les cas où nous essayons de comparer des chaînes qui pourraient provenir de différentes sources, mais qui, nous le savons, finiront par avoir les mêmes valeurs - un scénario assez courant pour les chaînes en ligne dans notre code. Par exemple, si nous avons une variable nomméeconnection_state
et que nous souhaitons savoir dans lequel des états suivants se['connecting', 'connected', 'disconnecting', 'disconnected']
trouve actuellement, nous pouvons utiliser directement le===
.Mais il y a plus. Juste au-dessus de 11.9.4, il y a une courte note:
Hmm. Et maintenant? Les cordes obtenues de l'extérieur peuvent, et très probablement, être unicodey étranges, et nos doux
===
ne leur rendront pas justice. En vientlocaleCompare
à la rescousse:On peut rentrer maintenant.
tl; dr;
Pour comparer des chaînes en javascript, utilisez
localeCompare
; si vous savez que les chaînes n'ont pas de composants non ASCII car ce sont, par exemple, des constantes de programme internes, alors cela===
fonctionne aussi.la source
Dans votre opération dans votre question initiale, vous effectuez l'opération suivante:
Donc, en supposant que ce sont des nombres (ie item1.attr = "1", item2.attr = "2") Vous pouvez toujours utiliser l'opérateur "===" (ou d'autres évaluateurs stricts) à condition de garantir le type. Les éléments suivants devraient fonctionner:
S'ils sont alphaNumeric, alors utilisez localCompare ().
la source
Comment ils fonctionnent des échantillons:
la source
la source
la source