Comment trier correctement un tableau d'entiers

849

Essayer d'obtenir la valeur la plus élevée et la plus basse d'un tableau dont je sais qu'il ne contiendra que des entiers semble être plus difficile que je ne le pensais.

var numArray = [140000, 104, 99];
numArray = numArray.sort();
alert(numArray)

Je m'attendrais à ce que cela se voit 99, 104, 140000. Au lieu de cela, cela se voit 104, 140000, 99. Il semble donc que le tri gère les valeurs sous forme de chaînes.

Existe-t-il un moyen d'obtenir la fonction de tri pour trier réellement sur la valeur entière?

peirix
la source
10
Notez que aucune des premières réponses face à toutes les valeurs à virgule flottante correctement; en particulier, aucun d'entre eux ne gère NaN. Ce serait bien de voir une réponse très bien classée qui traite de NaN.
Quuxplusone
3
BTW, si vous triez beaucoup et beaucoup d'entiers, il sera avantageux d'utiliser un algorithme de tri entier comme le tri par comptage . Le tri par comptage de temps prendra pour exécuter des échelles linéairement avec la taille de votre tableau: O (n). Alors que toutes les solutions utilisent ici un tri par comparaison moins efficace: O (n * log n).
Web_Designer
1
@Web_Designer Le tri de comptage est linéaire en ce qui concerne la plage de nombres, pas le tableau. Par exemple, le tri [1,1000000] prendra plus de 2 étapes, car l'algorithme devra analyser chaque index de tableau entre 1 et 1000000 pour voir quelle valeur de cellule est supérieure à 0.
yters
2
@yters En utilisant une table de hachage, vous ne pouvez faire attention qu'aux entiers qui apparaissent dans le tableau en cours de tri. Cela rend le tri linéaire par rapport à la taille du tableau.
Kevin
1
le moyen le plus rapide consiste à utiliser le module de tableau de tri isomorphe qui fonctionne nativement dans le navigateur et le nœud, prenant en charge tout type d'entrée, les champs calculés et les ordres de tri personnalisés.
Lloyd

Réponses:

1236

Par défaut, la méthode de tri trie les éléments par ordre alphabétique. Pour trier numériquement, ajoutez simplement une nouvelle méthode qui gère les tris numériques (sortNumber, illustré ci-dessous) -

var numArray = [140000, 104, 99];
numArray.sort(function(a, b) {
  return a - b;
});

console.log(numArray);

Dans ES6, vous pouvez simplifier cela avec les fonctions fléchées:

numArray.sort((a, b) => a - b); // For ascending sort
numArray.sort((a, b) => b - a); // For descending sort

Documentation:

Mozilla Array.prototype.sort()recommande cette fonction de comparaison pour les tableaux qui ne contiennent pas Infinity ou NaN. (Parce que Inf - Infc'est NaN, pas 0).

Également des exemples de tri d'objets par clé.

aks
la source
149
Agréable. Mais n'y a-t-il vraiment aucun moyen prêt à l'emploi pour obtenir un tri numérique à partir de javascript?
peirix
39
ahah c'est hors de la boîte! Mais si vous n'êtes vraiment pas pratique, vous pouvez lier des fonctions à la classe de classe de tableau au tout début de votre javascript: // Array.prototype.sortNormal = function () {return this.sort (function (a, b) {return a - b})} // Maintenant, appeler .sortNormal () sur n'importe quel tableau le triera numériquement
Jack Franzen
13
Pourquoi ab et non a> b. Je suggère le dernier afin d'éviter les erreurs de fonctionnement de la machine
Luca Davanzo
35
@Velthune La fonction de comparaison doit renvoyer -1, 0 ou +1. a> b ne renverra que vrai ou faux.
Iván Pérez
48
Ce code peut être raccourci à l'aide d'une fonction flèche . numberArray.sort((a, b) => (a - b));Yay! Je pense que cela est proche de la méthode prête à l'emploi. Remarque: vérifiez si votre moteur JS prend en charge les fonctions fléchées.
Константин Ван
174

Sur la base de toutes les réponses ci-dessus, elles peuvent également être effectuées sur une seule ligne comme celle-ci:

var numArray = [140000, 104, 99];

// ES5
numArray = numArray.sort(function (a, b) {  return a - b;  });

// ES2015
numArray = numArray.sort((a, b) => a - b);

//outputs: 99, 104, 140000
MarzSocks
la source
8
@bodyflex fixe: var arr = [140000, 104, 99].sort(function(a,b) { return a-b; });. Ou plus compact, dans ES6let arr = [140000, 104, 99].sort((a,b) => a-b);
00500005
1
Comme je l'ai dit dans un commentaire ci-dessus, les fonctions fléchées ne conviennent pas ici et je découragerais quiconque de les utiliser de cette façon. Vous utilisez un effet secondaire de la syntaxe de la flèche pour découper les mots functionet return, mais n'utilisez pas réellement le véritable objectif de la fonction flèche de passer this. Ce code implique qu'un thispassage de contexte se produit, mais ce n'est pas le cas. Confus pour les autres développeurs de lire votre code, juste pour enregistrer quelques caractères. Ne dépendez pas des effets secondaires - codez avec un but!
bambery
12
@bambery Je ne pense pas que vous ayez besoin d'utiliser une fonction flèche exclusivement pour les changements de contexte…
Ted Morin
7
@bambery, vous comprenez mal ce que fait la fonction flèche. Vous pensez que cela passe thisen quelque sorte dans la fonction, mais ce n'est pas vrai. Il néglige en fait de créer un thiset la argumentsvariable qui écrasent généralement les variables parentes. La seule raison que vous pouvez utiliser thisdans une fonction de flèche est la portée lexicale.
cuth
2
@bambery qui n'a pas bien vieilli ... trois ans plus tard et le développement javascript moderne utilise presque exclusivement les fonctions fléchées. :)
Kip
71

array.sort fait un tri lexicographique par défaut, pour un tri numérique, fournissez votre propre fonction. Voici un exemple simple:

function compareNumbers(a, b)
{
    return a - b;
}

numArray.sort(compareNumbers);

Notez également que le tri fonctionne "sur place", il n'y a pas besoin d'affectation.

Paul Dixon
la source
Je n'ai pas compris le code ci-dessus, comment le "retour a-b" fait-il le tri ascendant?
vikramvi
si a <b, compareNumbers renvoie un nombre négatif. Si a> b, ce sera positif. Si égal, il renvoie 0.
Paul Dixon
38

Cette réponse est équivalente à certaines des réponses existantes, mais les fonctions de flèche ECMAScript 6 fournissent une syntaxe beaucoup plus compacte qui nous permet de définir une fonction de tri en ligne sans sacrifier la lisibilité:

numArray = numArray.sort((a, b) => a - b);

Il est pris en charge dans la plupart des navigateurs aujourd'hui .

jjjjs
la source
1
"sans sacrifier la lisibilité". C'est subjectif. Avec quelques entiers simples, il est lisible. Lorsque vous travaillez avec des objets plus complexes et que vous souhaitez trier sur une propriété, pas tellement.
Tristan
3
@Tristan, le tri sur une propriété d'un objet peut toujours être fait assez proprement en utilisant cette syntaxe. Si la propriété de l'objet que vous souhaitez trier est un nombre, vous pouvez le faire: objArray=objArray.sort((a,b)=>a.numProperty - b.numProperty);et si la propriété est une chaîne, vous pouvez le faire: objArray=objArray.sort((a,b)=>a.strProperty.localeCompare(b.strProperty))‌​;cela étant dit, cette question pose spécifiquement la question du tri d'un tableau d'entiers
jjjjs
34

Je suis surpris que tout le monde recommande de passer une fonction de comparateur à sort(), ce qui rend le tri vraiment lent!

Pour trier les nombres, créez simplement n'importe quel tableau typé :

var numArray = new Uint32Array([140000, 104, 99]);
numArray = numArray.sort();
alert(numArray)

dy_
la source
4
L'utilisation d'un TypedArray accélère le tri d'environ 5 fois. Si vous voulez aller encore plus vite, le package npm de hpc-algorithms implémente Radix Sort et Counting Sort que plusieurs réponses suggèrent ici.
DragonSpit
wow, je ne savais pas que cela existait!
pixelearth
21

La raison pour laquelle la fonction de tri se comporte si bizarrement

De la documentation :

[...] le tableau est trié selon la valeur du point de code Unicode de chaque caractère, selon la conversion de chaîne de chaque élément.

Si vous imprimez les valeurs de points unicode du tableau, cela deviendra clair.

console.log("140000".charCodeAt(0));
console.log("104".charCodeAt(0));
console.log("99".charCodeAt(0));

//Note that we only look at the first index of the number "charCodeAt(  0  )"

Cela renvoie: "49, 49, 57".

49 (unicode value of first number at 140000)
49 (unicode value of first number at 104)
57 (unicode value of first number at 99)

Maintenant, comme 140000 et 104 ont renvoyé les mêmes valeurs (49), il coupe le premier index et vérifie à nouveau:

console.log("40000".charCodeAt(0));
console.log("04".charCodeAt(0));

//Note that we only look at the first index of the number "charCodeAt(  0  )"

52 (unicode value of first number at 40000)
40 (unicode value of first number at 04)

Si nous trions cela, nous obtiendrons:

40 (unicode value of first number at 04)
52 (unicode value of first number at 40000)

donc 104 vient avant 140000.

Le résultat final sera donc:

var numArray = [140000, 104, 99];
numArray = numArray.sort();
console.log(numArray)

104, 140000, 99

Conclusion:

sort()fait le tri en ne regardant que le premier index des nombres. sort()ne se soucie pas si un nombre entier est plus grand qu'un autre, il compare la valeur de l'unicode des chiffres, et s'il y a deux valeurs unicode égales, il vérifie s'il y a un chiffre suivant et le compare également.

Pour trier correctement, vous devez passer une fonction de comparaison sort()comme expliqué ici .

Noir
la source
Astuce: Ce n'est que mon explication, je n'ai pas réellement recherché le code. Alors ne faites pas entièrement confiance à cette réponse.
Black
17

Je suis d'accord avec aks, cependant au lieu d'utiliser

return a - b;

Tu devrais utiliser

return a > b ? 1 : a < b ? -1 : 0;
user3587638
la source
18
Pouvez-vous expliquer pourquoi quelqu'un devrait utiliser votre opération ternaire plus illisible? Autant que je sache, cela aurait le même résultat.
stefannew
6
Cette réponse prend également en considération des valeurs égales et les laisse au même endroit.
Maarten00
23
Et a - b non?
Bryan Rayner
12
"return ab" peut être adéquat pour le cas particulier de cette question (javascript, et tous les éléments d'entrée connus pour être des entiers), mais personnellement je préfère la forme ternaire parce qu'elle est plus canonique - cela fonctionne dans plus de cas, dans plus de langages de programmation , avec plus de types de données. Par exemple, en C, ab peut déborder, conduisant au tri en boucle sans fin, à la corruption de la mémoire, au plantage, etc. Cela dit, même la forme ternaire ne fonctionnera pas correctement si des NaN ou des types mixtes sont impliqués.
Don Hatch
8
Le >et <toujours comparer a et b en tant que chaînes.
vriesdemichael
11

Dans le nouveau monde ES6, il est beaucoup plus facile de faire un tri

numArray.sort((a,b) => a-b);

C'est tout ce dont vous avez besoin :)

Chait
la source
10

En JavaScript, le comportement par défaut de la méthode sort () consiste à trier les valeurs d'un tableau par ordre alphabétique.

Pour trier par numéro, vous devez définir une fonction de tri numérique (ce qui est très simple):

...
function sortNumber(a, b)
{
  return a - b;
}

numArray = numArray.sort(sortNumber);
Peter Mortensen
la source
8

Array.prototype.sort () est la méthode incontournable pour trier les tableaux, mais il y a quelques problèmes dont nous devons être conscients.

L'ordre de tri est par défaut lexicographique et non numérique quels que soient les types de valeurs dans le tableau. Même si le tableau contient tous les nombres, toutes les valeurs seront converties en chaîne et triées lexicographiquement.

Devrions-nous donc avoir besoin de personnaliser la méthode sort () et reverse () comme ci-dessous.

URL référée

Pour trier les nombres à l'intérieur du tableau

numArray.sort(function(a, b)
{
    return a - b;
});

Pour inverser les nombres à l'intérieur du tableau

numArray.sort(function(a, b)
{
    return b - a;
});

URL référée

Merbin Joe
la source
6

La question a déjà été répondue, le plus court est d'utiliser la sort()méthode. Mais si vous cherchez d'autres façons de trier votre tableau de nombres et que vous aimez aussi les cycles, vérifiez les points suivants

Tri par insertion

Ascendant:

var numArray = [140000, 104, 99];
for (var i = 0; i < numArray.length; i++) {
    var target = numArray[i];
    for (var j = i - 1; j >= 0 && (numArray[j] > target); j--) {
        numArray[j+1] = numArray[j];
    }
    numArray[j+1] = target
}
console.log(numArray);

Descendant:

var numArray = [140000, 104, 99];
for (var i = 0; i < numArray.length; i++) {
    var target = numArray[i];
    for (var j = i - 1; j >= 0 && (numArray[j] < target); j--) {
        numArray[j+1] = numArray[j];
    }
    numArray[j+1] = target
}
console.log(numArray);

Tri de sélection:

Ascendant:

var numArray = [140000, 104, 99];
for (var i = 0; i < numArray.length - 1; i++) {
    var min = i;
    for (var j = i + 1; j < numArray.length; j++) {
        if (numArray[j] < numArray[min]) {
            min = j;
        }
    }
    if (min != i) {
        var target = numArray[i];
        numArray[i] = numArray[min];
        numArray[min] = target;
    }
}
console.log(numArray);

Descendant:

var numArray = [140000, 104, 99];
for (var i = 0; i < numArray.length - 1; i++) {
    var min = i;
    for (var j = i + 1; j < numArray.length; j++) {
        if (numArray[j] > numArray[min]) {
            min = j;
        }
    }
    if (min != i) {
        var target = numArray[i];
        numArray[i] = numArray[min];
        numArray[min] = target;
    }
}
console.log(numArray);

S'amuser

Suicide commercial
la source
Certains d'entre eux sont- ils réellement plus rapides pour les petits tableaux que l'utilisation sort()sur un TypedArray comme cette réponse le suggère . Ils ne seront certainement pas plus rapides pour les tableaux de taille moyenne à grande car ce sont des algorithmes O (n ^ 2).
Peter Cordes
5

La fonction «numériquement» ci-dessous sert à trier le tableau de nombres numériquement dans de nombreux cas lorsqu'elle est fournie en tant que fonction de rappel:

function numerically(a, b){
    return a-b;
}

array.sort(numerically); 

Mais dans de rares cas, où le tableau contient des nombres très grands et négatifs, une erreur de débordement peut se produire car le résultat de ab devient plus petit que le plus petit nombre auquel JavaScript peut faire face.

Donc, une meilleure façon d'écrire numériquement la fonction est la suivante:

function numerically(a, b){
   if(a < b){
      return -1;
   } else if(a > b){
      return 1;
   } else {
      return 0;
   }
}
leet101
la source
1
Les nombres JavaScript sont en virgule flottante. IEEE754 définit les règles de dépassement et de dépassement, y compris le dépassement vers + -Infinity et le dépassement vers sous-normal ou + -0,0. Je ne pense pas que la soustraction de deux nombres puisse déborder à + -0,0 même s'ils sont à la fois grands et égaux à proximité. La différence entre deux doubles est toujours représentable comme un autre double non nul (à moins qu'il ne déborde, comme DBL_MIN - DBL_MAX) mais un dépassement de capacité n'est pas possible. L'annulation catastrophique rend le résultat imprécis, perdant la plupart de ses "chiffres significatifs", mais a-bsera toujours non nul et aura le bon signe pour a! = B.
Peter Cordes
4

pour gérer undefined, null et NaN: Null se comporte comme 0, NaN et undefined va se terminer.

array = [3, 5, -1, 1, NaN, 6, undefined, 2, null]
array.sort((a,b) => isNaN(a) || a-b)
// [-1, null, 1, 2, 3, 5, 6, NaN, undefined]
Ali Khosro
la source
3

Pour un tableau normal de valeurs d'éléments uniquement:

function sortArrayOfElements(arrayToSort) {
    function compareElements(a, b) {
        if (a < b)
            return -1;
        if (a > b)
            return 1;
        return 0;
    }

    return arrayToSort.sort(compareElements);
}

e.g. 1:
var array1 = [1,2,545,676,64,2,24]
**output : [1, 2, 2, 24, 64, 545, 676]**

var array2 = ["v","a",545,676,64,2,"24"]
**output: ["a", "v", 2, "24", 64, 545, 676]**

Pour un tableau d'objets:

function sortArrayOfObjects(arrayToSort, key) {
    function compareObjects(a, b) {
        if (a[key] < b[key])
            return -1;
        if (a[key] > b[key])
            return 1;
        return 0;
    }

    return arrayToSort.sort(compareObjects);
}

e.g. 1: var array1= [{"name": "User4", "value": 4},{"name": "User3", "value": 3},{"name": "User2", "value": 2}]

**output : [{"name": "User2", "value": 2},{"name": "User3", "value": 3},{"name": "User4", "value": 4}]**
Umesh
la source
2

Mise à jour! Faites défiler vers le bas de la réponse pour smartSortl'additif prop qui donne encore plus de plaisir!
Trie les tableaux de tout !

Ma forme préférée personnelle de cette fonction permet un paramètre pour Ascendant ou Descendant:

function intArraySort(c, a) {
    function d(a, b) { return b - a; }
    "string" == typeof a && a.toLowerCase();
    switch (a) {
        default: return c.sort(function(a, b) { return a - b; });
        case 1:
                case "d":
                case "dc":
                case "desc":
                return c.sort(d)
    }
};

Utilisation aussi simple que:

var ara = function getArray() {
        var a = Math.floor(Math.random()*50)+1, b = [];
        for (i=0;i<=a;i++) b.push(Math.floor(Math.random()*50)+1);
        return b;
    }();

//    Ascending
intArraySort(ara);
console.log(ara);

//    Descending
intArraySort(ara, 1);
console.log(ara);

//    Ascending
intArraySort(ara, 'a');
console.log(ara);

//    Descending
intArraySort(ara, 'dc');
console.log(ara);

//    Ascending
intArraySort(ara, 'asc');
console.log(ara);

jsFiddle


Ou exemple d'extrait de code ici!

function intArraySort(c, a) {
	function d(a, b) { return b - a }
	"string" == typeof a && a.toLowerCase();
	switch (a) {
		default: return c.sort(function(a, b) { return a - b });
		case 1:
		case "d":
		case "dc":
		case "desc":
		return c.sort(d)
	}
};

function tableExample() {
	var d = function() {
			var a = Math.floor(50 * Math.random()) + 1,
				b = [];
			for (i = 0; i <= a; i++) b.push(Math.floor(50 * Math.random()) + 1);
			return b
		},
		a = function(a) {
			var b = $("<tr/>"),
				c = $("<th/>").prependTo(b);
			$("<td/>", {
				text: intArraySort(d(), a).join(", ")
			}).appendTo(b);
			switch (a) {
				case 1:
				case "d":
				case "dc":
				case "desc":
					c.addClass("desc").text("Descending");
					break;
				default:
					c.addClass("asc").text("Ascending")
			}
			return b
		};
	return $("tbody").empty().append(a(), a(1), a(), a(1), a(), a(1), a(), a(1), a(), a(1), a(), a(1))
};

tableExample();
table { border-collapse: collapse; }
th, td { border: 1px solid; padding: .25em .5em; vertical-align: top; }
.asc { color: red; }
.desc { color: blue }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table><tbody></tbody></table>


.smartSort ('asc' | 'desc')

Maintenant, amusez-vous encore plus avec une méthode de tri qui trie un tableau plein de plusieurs éléments! Ne couvre pas actuellement "associatif" (aka, clés de chaîne), mais il couvre tous les types de valeur! Non seulement il triera les valeurs multiples ascou en descconséquence, mais il maintiendra également une "position" constante des "groupes" de valeurs. En d'autres termes; les entiers sont toujours les premiers, puis viennent les chaînes, puis les tableaux (oui, je fais cela multidimensionnel!), puis les objets (non filtrés, élément, date), et enfin les indéfinis et les nuls!

"Pourquoi?" tu demandes. Pourquoi pas!

Maintenant disponible en 2 saveurs! Le premier nécessite des navigateurs plus récents car il utilise Object.definePropertypour ajouter la méthode à l' Array.protoypeobjet. Cela permet de faciliter la naturelle utilisation, tels que: myArray.smartSort('a'). Si vous avez besoin d'implémenter pour des navigateurs plus anciens, ou si vous n'aimez tout simplement pas modifier des objets natifs, faites défiler jusqu'à la version Méthode uniquement .

/* begin */
/* KEY NOTE! Requires EcmaScript 5.1 (not compatible with older browsers) */
;;(function(){if(Object.defineProperty&&!Array.prototype.smartSort){var h=function(a,b){if(null==a||void 0==a)return 1;if(null==b||void 0==b)return-1;var c=typeof a,e=c+typeof b;if(/^numbernumber$/ig.test(e))return a-b;if(/^stringstring$/ig.test(e))return a>b;if(/(string|number){2}/ig.test(e))return/string/i.test(c)?1:-1;if(/number/ig.test(e)&&/object/ig.test(e)||/string/ig.test(e)&&/object/ig.test(e))return/object/i.test(c)?1:-1;if(/^objectobject$/ig.test(e)){a instanceof Array&&a.smartSort("a");b instanceof Array&&b.smartSort("a");if(a instanceof Date&&b instanceof Date)return a-b;if(a instanceof Array&&b instanceof Array){var e=Object.keys(a),g=Object.keys(b),e=e.concat(g).smartSort("a"),d;for(d in e)if(c=e[d],a[c]!=b[c])return d=[a[c],b[c]].smartSort("a"),a[c]==d[0]?-1:1;var f=[a[Object.keys(a)[0]],b[Object.keys(b)[0]]].smartSort("a");return a[Object.keys(a)[0]]==f[0]?-1:1}if(a instanceof Element&&b instanceof Element){if(a.tagName==b.tagName)return e=[a.id,b.id].smartSort("a"),a.id==e[0]?1:-1;e=[a.tagName, b.tagName].smartSort("a");return a.tagName==e[0]?1:-1}if(a instanceof Date||b instanceof Date)return a instanceof Date?1:-1;if(a instanceof Array||b instanceof Array)return a instanceof Array?-1:1;e=Object.keys(a);g=Object.keys(b);e.concat(g).smartSort("a");for(c=0;20>c;c++){d=e[c];f=g[c];if(a.hasOwnProperty(d)&&b.hasOwnProperty(f)){if(a[d]instanceof Element&&b[f]instanceof Element){if(a[d].tagName==b[f].tagName)return c=[a[d].id,b[f].id].smartSort("a"),a[d].id==c[0]?-1:1;c=[a[d].tagName,b[f].tagName].smartSort("d"); return a[d].tagName==c[0]?1:-1}if(a[d]instanceof Element||b[f]instanceof Element)return a[d]instanceof Element?1:-1;if(a[d]!=b[f])return c=[a[d],b[f]].smartSort("a"),a[d]==c[0]?-1:1}if(a.hasOwnProperty(d)&&a[d]instanceof Element)return 1;if(b.hasOwnProperty(f)&&b[f]instanceof Element||!a.hasOwnProperty(d))return-1;if(!b.hasOwnProperty(d))return 1}c=[a[Object.keys(a)[0]],b[Object.keys(b)[0]]].smartSort("d");return a[Object.keys(a)[0]]==c[0]?-1:1}g=[a,b].sort();return g[0]>g[1]},k=function(a,b){if(null== a||void 0==a)return 1;if(null==b||void 0==b)return-1;var c=typeof a,e=c+typeof b;if(/^numbernumber$/ig.test(e))return b-a;if(/^stringstring$/ig.test(e))return b>a;if(/(string|number){2}/ig.test(e))return/string/i.test(c)?1:-1;if(/number/ig.test(e)&&/object/ig.test(e)||/string/ig.test(e)&&/object/ig.test(e))return/object/i.test(c)?1:-1;if(/^objectobject$/ig.test(e)){a instanceof Array&&a.smartSort("d");b instanceof Array&&b.smartSort("d");if(a instanceof Date&&b instanceof Date)return b-a;if(a instanceof Array&&b instanceof Array){var e=Object.keys(a),g=Object.keys(b),e=e.concat(g).smartSort("a"),d;for(d in e)if(c=e[d],a[c]!=b[c])return d=[a[c],b[c]].smartSort("d"),a[c]==d[0]?-1:1;var f=[a[Object.keys(a)[0]],b[Object.keys(b)[0]]].smartSort("d");return a[Object.keys(a)[0]]==f[0]?-1:1}if(a instanceof Element&&b instanceof Element){if(a.tagName==b.tagName)return e=[a.id,b.id].smartSort("d"),a.id==e[0]?-1:1;e=[a.tagName,b.tagName].smartSort("d");return a.tagName==e[0]?-1:1}if(a instanceof Date||b instanceof Date)return a instanceof Date?1:-1;if(a instanceof Array||b instanceof Array)return a instanceof Array?-1:1;e=Object.keys(a);g=Object.keys(b);e.concat(g).smartSort("a");for(c=0;20>c;c++){d=e[c];f=g[c];if(a.hasOwnProperty(d)&&b.hasOwnProperty(f)){if(a[d]instanceof Element&&b[f]instanceof Element){if(a[d].tagName==b[f].tagName)return c=[a[d].id,b[f].id].smartSort("d"),a[d].id==c[0]?-1:1;c=[a[d].tagName,b[f].tagName].smartSort("d");return a[d].tagName==c[0]?-1:1}if(a[d]instanceof Element||b[f]instanceof Element)return a[d]instanceof Element?1:-1;if(a[d]!=b[f])return c=[a[d],b[f]].smartSort("d"),a[d]==c[0]?-1:1}if(a.hasOwnProperty(d)&&a[d]instanceof Element)return 1;if(b.hasOwnProperty(f)&&b[f]instanceof Element)return-1;if(!a.hasOwnProperty(d))return 1;if(!b.hasOwnProperty(d))return-1}c=[a[Object.keys(a)[0]],b[Object.keys(b)[0]]].smartSort("d");return a[Object.keys(a)[0]]==c[0]?-1:1}g=[a,b].sort();return g[0]<g[1]};Object.defineProperty(Array.prototype,"smartSort",{value:function(){return arguments&& (!arguments.length||1==arguments.length&&/^a([sc]{2})?$|^d([esc]{3})?$/i.test(arguments[0]))?this.sort(!arguments.length||/^a([sc]{2})?$/i.test(arguments[0])?h:k):this.sort()}})}})();
/* end */

jsFiddle Array.prototype.smartSort ('asc | desc')


L'utilisation est simple! Faites d'abord un tableau fou comme:

window.z = [ 'one', undefined, $('<span />'), 'two', null, 2, $('<div />', { id: 'Thing' }), $('<div />'), 4, $('<header />') ];
z.push(new Date('1/01/2011'));
z.push('three');
z.push(undefined);
z.push([ 'one', 'three', 'four' ]);
z.push([ 'one', 'three', 'five' ]);
z.push({ a: 'a', b: 'b' });
z.push({ name: 'bob', value: 'bill' });
z.push(new Date());
z.push({ john: 'jill', jack: 'june' });
z.push([ 'abc', 'def', [ 'abc', 'def', 'cba' ], [ 'cba', 'def', 'bca' ], 'cba' ]);
z.push([ 'cba', 'def', 'bca' ]);
z.push({ a: 'a', b: 'b', c: 'c' });
z.push({ a: 'a', b: 'b', c: 'd' });

Ensuite, triez-le simplement!

z.smartSort('asc'); // Ascending
z.smartSort('desc'); // Descending

Méthode uniquement

Identique à la précédente, sauf comme une simple méthode!

/* begin */
/* KEY NOTE! Method `smartSort` is appended to native `window` for global use. If you'd prefer a more local scope, simple change `window.smartSort` to `var smartSort` and place inside your class/method */
window.smartSort=function(){if(arguments){var a,b,c;for(c in arguments)arguments[c]instanceof Array&&(a=arguments[c],void 0==b&&(b="a")),"string"==typeof arguments[c]&&(b=/^a([sc]{2})?$/i.test(arguments[c])?"a":"d");if(a instanceof Array)return a.sort("a"==b?smartSort.asc:smartSort.desc)}return this.sort()};smartSort.asc=function(a,b){if(null==a||void 0==a)return 1;if(null==b||void 0==b)return-1;var c=typeof a,e=c+typeof b;if(/^numbernumber$/ig.test(e))return a-b;if(/^stringstring$/ig.test(e))return a> b;if(/(string|number){2}/ig.test(e))return/string/i.test(c)?1:-1;if(/number/ig.test(e)&&/object/ig.test(e)||/string/ig.test(e)&&/object/ig.test(e))return/object/i.test(c)?1:-1;if(/^objectobject$/ig.test(e)){a instanceof Array&&a.sort(smartSort.asc);b instanceof Array&&b.sort(smartSort.asc);if(a instanceof Date&&b instanceof Date)return a-b;if(a instanceof Array&&b instanceof Array){var e=Object.keys(a),g=Object.keys(b),e=smartSort(e.concat(g),"a"),d;for(d in e)if(c=e[d],a[c]!=b[c])return d=smartSort([a[c], b[c]],"a"),a[c]==d[0]?-1:1;var f=smartSort([a[Object.keys(a)[0]],b[Object.keys(b)[0]]],"a");return a[Object.keys(a)[0]]==f[0]?-1:1}if(a instanceof Element&&b instanceof Element){if(a.tagName==b.tagName)return e=smartSort([a.id,b.id],"a"),a.id==e[0]?1:-1;e=smartSort([a.tagName,b.tagName],"a");return a.tagName==e[0]?1:-1}if(a instanceof Date||b instanceof Date)return a instanceof Date?1:-1;if(a instanceof Array||b instanceof Array)return a instanceof Array?-1:1;e=Object.keys(a);g=Object.keys(b);smartSort(e.concat(g), "a");for(c=0;20>c;c++){d=e[c];f=g[c];if(a.hasOwnProperty(d)&&b.hasOwnProperty(f)){if(a[d]instanceof Element&&b[f]instanceof Element){if(a[d].tagName==b[f].tagName)return c=smartSort([a[d].id,b[f].id],"a"),a[d].id==c[0]?-1:1;c=smartSort([a[d].tagName,b[f].tagName],"a");return a[d].tagName==c[0]?-1:1}if(a[d]instanceof Element||b[f]instanceof Element)return a[d]instanceof Element?1:-1;if(a[d]!=b[f])return c=smartSort([a[d],b[f]],"a"),a[d]==c[0]?-1:1}if(a.hasOwnProperty(d)&&a[d]instanceof Element)return 1; if(b.hasOwnProperty(f)&&b[f]instanceof Element||!a.hasOwnProperty(d))return-1;if(!b.hasOwnProperty(d))return 1}c=smartSort([a[Object.keys(a)[0]],b[Object.keys(b)[0]]],"a");return a[Object.keys(a)[0]]==c[0]?1:-1}g=[a,b].sort();return g[0]>g[1]};smartSort.desc=function(a,b){if(null==a||void 0==a)return 1;if(null==b||void 0==b)return-1;var c=typeof a,e=c+typeof b;if(/^numbernumber$/ig.test(e))return b-a;if(/^stringstring$/ig.test(e))return b>a;if(/(string|number){2}/ig.test(e))return/string/i.test(c)? 1:-1;if(/number/ig.test(e)&&/object/ig.test(e)||/string/ig.test(e)&&/object/ig.test(e))return/object/i.test(c)?1:-1;if(/^objectobject$/ig.test(e)){a instanceof Array&&a.sort(smartSort.desc);b instanceof Array&&b.sort(smartSort.desc);if(a instanceof Date&&b instanceof Date)return b-a;if(a instanceof Array&&b instanceof Array){var e=Object.keys(a),g=Object.keys(b),e=smartSort(e.concat(g),"a"),d;for(d in e)if(c=e[d],a[c]!=b[c])return d=smartSort([a[c],b[c]],"d"),a[c]==d[0]?-1:1;var f=smartSort([a[Object.keys(a)[0]], b[Object.keys(b)[0]]],"d");return a[Object.keys(a)[0]]==f[0]?-1:1}if(a instanceof Element&&b instanceof Element){if(a.tagName==b.tagName)return e=smartSort([a.id,b.id],"d"),a.id==e[0]?-1:1;e=smartSort([a.tagName,b.tagName],"d");return a.tagName==e[0]?-1:1}if(a instanceof Date||b instanceof Date)return a instanceof Date?1:-1;if(a instanceof Array||b instanceof Array)return a instanceof Array?-1:1;e=Object.keys(a);g=Object.keys(b);smartSort(e.concat(g),"a");for(c=0;20>c;c++){d=e[c];f=g[c];if(a.hasOwnProperty(d)&& b.hasOwnProperty(f)){if(a[d]instanceof Element&&b[f]instanceof Element){if(a[d].tagName==b[f].tagName)return c=smartSort([a[d].id,b[f].id],"d"),a[d].id==c[0]?-1:1;c=smartSort([a[d].tagName,b[f].tagName],"d");return a[d].tagName==c[0]?-1:1}if(a[d]instanceof Element||b[f]instanceof Element)return a[d]instanceof Element?1:-1;if(a[d]!=b[f])return c=smartSort([a[d],b[f]],"d"),a[d]==c[0]?-1:1}if(a.hasOwnProperty(d)&&a[d]instanceof Element)return 1;if(b.hasOwnProperty(f)&&b[f]instanceof Element)return-1; if(!a.hasOwnProperty(d))return 1;if(!b.hasOwnProperty(d))return-1}c=smartSort([a[Object.keys(a)[0]],b[Object.keys(b)[0]]],"d");return a[Object.keys(a)[0]]==c[0]?-1:1}g=[a,b].sort();return g[0]<g[1]}
/* end */

Utilisation:

z = smartSort(z, 'asc'); // Ascending
z = smartSort(z, 'desc'); // Descending

jsFiddle, méthode smartSort (tableau, "asc | desc")

SpYk3HH
la source
2

Essayez ce code:

HTML:

<div id="demo"></div>

Code JavaScript:

<script>
    (function(){
        var points = [40, 100, 1, 5, 25, 10];
        document.getElementById("demo").innerHTML = points;
        points.sort(function(a, b){return a-b});
        document.getElementById("demo").innerHTML = points;
    })();
</script>
Sunny SM
la source
2

Essayez ce code comme ci-dessous

var a = [5, 17, 29, 48, 64, 21];
function sortA(arr) {
return arr.sort(function(a, b) {
return a - b;
})
;} 
alert(sortA(a));
user7125929
la source
n'est-ce pas vrai?
user7125929
1
var numArray = [140000, 104, 99];
numArray = numArray.sort((a,b) => a-b);
alert(numArray)
Vardaman PK
la source
4
Bienvenue dans StackOverflow. Votre réponse est identique à la réponse acceptée. Pouvez-vous ajouter une explication à votre réponse pour dire pourquoi cela devrait être préféré à la réponse acceptée?
Simply Ged
1

Bien que cela ne soit pas requis en JavaScript, si vous souhaitez que strictement retourner -1, 0 ou 1 (similaire à la façon dont l' opérateur de vaisseau spatial fonctionne en PHP), vous pouvez l'utiliser .sort() compareFunctionMath.sign()

Ce qui compareFunctionsuit renvoie strictement -1, 0 ou 1:

numArray.sort((a, b) => Math.sign(a - b));

Remarque: Math.sign() n'est pas pris en charge dans Internet Explorer.

Grant Miller
la source
0

Voici la solution déjà proposée et acceptée comme méthode sur le prototype Array:

Array.prototype.sortNumeric = function () {
    return this.sort((a, b) => a - b);
};
Array.prototype.sortNumericDesc = function () {
    return this.sort((a, b) => b - a);
};
Erreur 404
la source
0

Comme la méthode de tri convertit les éléments du tableau en chaîne. Donc, ci-dessous fonctionne également très bien avec des nombres décimaux avec des éléments de tableau.

let productPrices = [10.33, 2.55, 1.06, 5.77];
console.log(productPrices.sort((a,b)=>a-b));

Et vous donne le résultat attendu.

Anshul Chaurasia
la source
0

Substitution de la méthode de tri.

Array.prototype.sortInt = function(){
    this.sort(function(a,b){return a-b});
}


numbers = [12,8,21,5,1,34];
numbers.sortInt()
//output -> [1,5,8,12,21,34]
sandes
la source
0

La fonction de tri par défaut est le tri dans l'ordre du dictionnaire:

var ar = [10000,3,200];
console.log(ar.sort());
//it will sort like :=> [10000, 200, 3]

Celui ci-dessus n'est pas le cas que nous voulons pour les chiffres. Donc, si vous avez des entiers et que la fonction de tri par défaut ne fonctionne pas (car elle trie dans l'ordre du dictionnaire), vous devez implémenter votre propre fonction:

var ar = [10000,3,-09,200];
function customSortHelpForNumber(number1, number2){
     return number1-number2;
}
console.log(ar.sort(customSortHelpForNumber));
//it will sort like :=> [3, 200, 10000]

J'espère que vous avez une question en tête: comment ça marche? Ici, lorsque nous fournissons une méthode dans la fonction de tri, il passe à chaque fois deux nombres et si le nombre revient

  • -ve valeur ou 0, il conserve le premier nombre à sa place
  • + je l'apprécie échanger l'endroit.

En suivant ceci pour tous les nombres, il trie le tableau d'entiers.

Si vous utilisez ES6, écrivez une fonction de flèche:

console.log(ar.sort((num1,num2)=> num1-num2));
    //it will sort like :=> [3, 200, 10000]
Justin
la source
-1

Voici ma fonction de tableau de tri dans la bibliothèque d'utils:

sortArray: function(array) {
    array.sort(function(a, b) {
        return a > b;
    });
},

# Let's test a string array
var arr = ['bbc', 'chrome', 'aux', 'ext', 'dog'];
utils.sortArray(arr);
console.log(arr);
>>> ["aux", "bbc", "chrome", "dog", "ext", remove: function]

# Let's test a number array
var arr = [55, 22, 1425, 12, 78];
utils.sortArray(arr);
console.log(arr);
>>> [12, 22, 55, 78, 1425, remove: function]
firestoke
la source
3
C'est tout à fait faux! La fonction de tri doit renvoyer des nombres négatifs, 0 ou positifs, pas vrai ou faux.
jperelli
Comme @jperelli l'a mentionné, la fonction de tri a besoin d'un nombre, et non d'un booléen, pour être retourné (et étant donné qu'il y a 3 états possibles, égaux, au-dessus et en dessous, cela est nécessaire pour avoir un tri stable). Comme votre réponse est indiquée, cela ne fonctionne pas. a-bdevrait être utilisé à la place. (Vous pouvez avoir de la fantaisie et faire un Number(a>b)-0.5, mais ce n'est toujours pas un type stable).
ecc521