Come ordinare correttamente un array di numeri interi


849

Cercare di ottenere il valore più alto e più basso da un array che so conterrà solo numeri interi sembra essere più difficile di quanto pensassi.

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

Mi aspetterei che questo mostri 99, 104, 140000. Invece mostra 104, 140000, 99. Quindi sembra che l'ordinamento stia gestendo i valori come stringhe.

C'è un modo per far sì che la funzione di ordinamento esegua effettivamente l'ordinamento sul valore intero?


10
Si noti che nessuna delle risposte migliori gestisce correttamente tutti i valori in virgola mobile; in particolare, nessuno di loro gestisce NaN. Sarebbe bello vedere una risposta di alto livello che si occupa NaN.
Quuxplusone,

3
A proposito, se stai ordinando un sacco di numeri interi, sarà vantaggioso utilizzare un algoritmo di ordinamento di numeri interi come contare l'ordinamento . Il tempo necessario all'ordinamento richiederà l'esecuzione delle scale in modo lineare con le dimensioni dell'array: O (n). Considerando che tutte le soluzioni qui usano un ordinamento comparativo che è meno efficiente: O (n * log n).
Web_Designer

1
@Web_Designer L'ordinamento del conteggio è lineare rispetto all'intervallo di numeri, non all'array. Ad esempio, l'ordinamento [1.1000000] richiederà più di 2 passaggi, poiché l'algoritmo dovrà eseguire la scansione di ciascun indice dell'array tra 1 e 1000000 per vedere quale valore della cella è maggiore di 0.

2
@yters Utilizzando una hashmap, puoi solo prestare attenzione agli interi che compaiono nella matrice ordinata. Questo rende l'ordinamento lineare e la dimensione dell'array.
Kevin,

1
il modo più rapido è utilizzare il modulo di ordinamento-array isomorfo che funziona nativamente sia nel browser che nel nodo, supportando qualsiasi tipo di input, campi calcolati e ordinamenti personalizzati.
Lloyd,

Risposte:


1236

Per impostazione predefinita, il metodo di ordinamento ordina gli elementi in ordine alfabetico. Per ordinare numericamente basta aggiungere un nuovo metodo che gestisce gli ordinamenti numerici (sortNumber, mostrato sotto) -

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

console.log(numArray);

In ES6, puoi semplificarlo con le funzioni freccia:

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

Documentazione:

Mozilla Array.prototype.sort()consiglia questa funzione di confronto per array che non contengono Infinity o NaN. (Perché Inf - Infè NaN, non 0).

Anche esempi di ordinamento di oggetti per chiave.


149
Bello. Ma non esiste davvero un modo predefinito per ottenere un ordinamento numerico da JavaScript?
peirix,

39
ahah questo è fuori dagli schemi! Ma se sei davvero poco pratico, puoi associare le funzioni alla classe della classe di array all'inizio del tuo javascript: // Array.prototype.sortNormal = function () {return this.sort (function (a, b) {return a - b})} // Ora chiamando .sortNormal () su qualsiasi array lo ordinerà numericamente
Jack Franzen,

13
Perché ab e non a> b. Suggerisco l'ultimo per evitare errori di funzionamento della macchina
Luca Davanzo,

35
@Velthune La funzione di confronto dovrebbe restituire -1, 0 o +1. a> b restituirà solo vero o falso.
Iván Pérez,

48
Questo codice può essere abbreviato utilizzando una funzione freccia . numberArray.sort((a, b) => (a - b));Sìì! Penso che questo sia vicino al modo out-of-the-box. Nota: controlla se il tuo motore JS supporta le funzioni freccia.
Константин Ван,

174

Basandosi su tutte le risposte di cui sopra, possono anche essere fatte in una riga come questa:

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

8
@bodyflex fisso: var arr = [140000, 104, 99].sort(function(a,b) { return a-b; });. O più compatto, in ES6let arr = [140000, 104, 99].sort((a,b) => a-b);
00500005

1
Come ho detto in un commento sopra, le funzioni delle frecce non vanno bene qui e scoraggerei chiunque dall'utilizzarle in questo modo. Stai usando un effetto collaterale della sintassi della freccia per ritagliare le parole functione return, in realtà, non stai usando il vero scopo del passaggio della funzione freccia this. Questo codice implica che sta thisavvenendo un certo passaggio di contesto, ma non lo è. Confusione per gli altri sviluppatori di leggere il tuo codice, solo per salvare alcuni caratteri. Non dipendere dagli effetti collaterali - codifica con lo scopo!
bambery,

12
@bambery Non penso che devi usare una funzione freccia esclusivamente per i cambiamenti di contesto ...
Ted Morin,

7
@bambery, in realtà fraintendi cosa sta facendo la funzione freccia. Pensi che in qualche modo passi thisnella funzione ma non è vero. In realtà trascura di creare ae thisla argumentsvariabile che di solito sovrascrive le variabili parent. L'unica ragione per cui è possibile utilizzare thisall'interno di una funzione freccia è l'ambito lessicale.
cuth

2
@bambery che non è invecchiato bene ... tre anni dopo e il moderno sviluppo javascript utilizza quasi esclusivamente le funzioni freccia. :)
Kip

71

array.sort esegue un ordinamento lessicografico per impostazione predefinita, per un ordinamento numerico, fornire la propria funzione. Ecco un semplice esempio:

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

numArray.sort(compareNumbers);

Si noti inoltre che l'ordinamento funziona "sul posto", non è necessario per l'assegnazione.


Non ho capito il codice sopra, come fa "return a - b" l'ordinamento crescente?
vikramvi,

se a <b, compareNumbers restituisce un numero negativo. Se a> b, sarà positivo. Se uguale, restituisce 0.
Paul Dixon

38

Questa risposta equivale ad alcune delle risposte esistenti, ma le funzioni freccia ECMAScript 6 forniscono una sintassi molto più compatta che ci consente di definire una funzione di ordinamento in linea senza sacrificare la leggibilità:

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

È supportato in maggior parte dei browser .


1
"senza sacrificare la leggibilità". Questo è soggettivo. Con alcuni interi semplici è leggibile. Quando si lavora con oggetti più complessi e si desidera ordinare su una proprietà, non tanto.
Tristan,

3
@Tristan, l'ordinamento su una proprietà di un oggetto può ancora essere fatto in modo abbastanza pulito usando questa sintassi. Se la proprietà dell'oggetto che vuoi ordinare è un numero che puoi fare: objArray=objArray.sort((a,b)=>a.numProperty - b.numProperty);e se la proprietà è una stringa che puoi fare: objArray=objArray.sort((a,b)=>a.strProperty.localeCompare(b.strProperty))‌​;Detto questo, questa domanda si pone specificamente sull'ordinamento di un array di numeri interi
jjjjs

34

Sono sorpreso dal motivo per cui tutti consigliano di passare una funzione di confronto sort(), che rende l'ordinamento molto lento!

Per ordinare i numeri, basta creare qualsiasi TypedArray :

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


4
L'uso di un TypedArray velocizza l'ordinamento di circa 5 volte. Se vuoi andare ancora più veloce, il pacchetto npm di algoritmi hpc implementa l'ordinamento e il conteggio Radix che diverse risposte suggeriscono qui.
DragonSpit,

wow, non sapevo che esistesse!
pixelearth

21

Il motivo per cui la funzione di ordinamento si comporta in modo strano

Dalla documentazione :

[...] l'array viene ordinato in base al valore del punto di codice Unicode di ciascun carattere, in base alla conversione di stringa di ciascun elemento.

Se si stampano i valori dei punti unicode dell'array, sarà chiaro.

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  )"

Ciò restituisce: "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)

Ora, poiché 140000 e 104 hanno restituito gli stessi valori (49), taglia il primo indice e verifica di nuovo:

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)

Se lo ordiniamo, otterremo:

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

quindi 104 arriva prima del 140000.

Quindi il risultato finale sarà:

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

104, 140000, 99

Conclusione:

sort()fa l'ordinamento solo guardando il primo indice dei numeri. sort()non importa se un numero intero è più grande di un altro, confronta il valore dell'unicode delle cifre e se ci sono due valori unicode uguali, controlla se esiste una cifra successiva e la confronta anche.

Per ordinare correttamente, devi passare una funzione di confronto a sort()come spiegato qui .


Suggerimento: questa è solo la mia spiegazione, in realtà non ho cercato il codice. Quindi non fidarti completamente di questa risposta.
Black

17

Sono d'accordo con aks, tuttavia invece di utilizzare

return a - b;

Dovresti usare

return a > b ? 1 : a < b ? -1 : 0;

18
Puoi spiegare perché qualcuno dovrebbe usare la tua operazione ternaria più illeggibile? Per quanto ne so, avrebbe lo stesso risultato.
Stefannew,

6
Questa risposta prende in considerazione anche gli stessi valori e li lascia nello stesso posto.
Maarten00,

23
E a - b no?
Bryan Rayner,

12
"return ab" potrebbe essere adeguato al caso particolare di questa domanda (javascript e tutti gli elementi di input noti come ints), ma personalmente preferisco la forma ternaria perché è più canonica, funziona in più casi, in più linguaggi di programmazione , con più tipi di dati. Ad esempio in C, ab può traboccare, portando al tipo di loop infinito, corrompendo la memoria, crash, ecc. Detto questo, anche la forma ternaria non funzionerà in modo sano se ci sono NaN o tipi misti coinvolti.
Don Hatch,

8
Il >e <ancora confrontare aeb come stringhe.
vriesdemichael,

11

Nel nuovo mondo ES6 è molto più facile fare una sorta

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

Questo è tutto ciò che serve :)


10

In JavaScript il comportamento predefinito del metodo sort () è di ordinare i valori in un array in ordine alfabetico.

Per ordinare per numero devi definire una funzione di ordinamento numerico (che è molto semplice):

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

numArray = numArray.sort(sortNumber);

8

Array.prototype.sort () è il metodo di ordinamento degli array, ma ci sono un paio di problemi di cui dobbiamo essere a conoscenza.

L'ordinamento è di default lessicografico e non numerico indipendentemente dai tipi di valori nell'array. Anche se l'array è composto da tutti i numeri, tutti i valori verranno convertiti in stringhe e ordinati lessicograficamente.

Quindi dovremmo personalizzare il metodo sort () e reverse () come di seguito.

URL di riferimento

Per ordinare i numeri all'interno dell'array

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

Per invertire i numeri all'interno dell'array

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

URL di riferimento


6

Alla domanda è già stata data una risposta, il modo più breve è usare sort() metodo. Ma se stai cercando altri modi per ordinare il tuo array di numeri e ami anche i cicli, controlla quanto segue

Ordinamento per inserzione

Ascendente:

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);

Discendente:

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);

Selezione ordinamento:

Ascendente:

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);

Discendente:

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);

Divertiti


Qualcuno di questi è effettivamente più veloce per array di piccole dimensioni rispetto all'utilizzo sort()su un TypedArray come suggerisce questa risposta . Certamente non saranno più veloci per array medio-grandi perché si tratta di algoritmi O (n ^ 2).
Peter Cordes,

5

La funzione "numericamente" di seguito ha lo scopo di ordinare numericamente un array di numeri in molti casi se fornito come funzione di callback:

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

array.sort(numerically); 

Ma in alcuni rari casi, in cui l'array contiene numeri molto grandi e negativi, può verificarsi un errore di overflow poiché il risultato di ab diventa più piccolo del numero più piccolo con cui JavaScript può far fronte.

Quindi un modo migliore di scrivere funzioni numeriche è il seguente:

function numerically(a, b){
   if(a < b){
      return -1;
   } else if(a > b){
      return 1;
   } else {
      return 0;
   }
}

1
I numeri JavaScript sono in virgola mobile. IEEE754 definisce le regole di overflow e underflow, tra cui overflow a + -Infinity e underflow su subnormale o + -0.0. Non penso che la sottrazione di due numeri possa essere underflow a + -0,0 anche se sono uguali sia grandi che vicini. La differenza tra due doppi è sempre rappresentabile come un altro doppio diverso da zero (a meno che non trabocchi, come DBL_MIN - DBL_MAX), ma il underflow non è possibile. La cancellazione catastrofica rende il risultato impreciso, perdendo la maggior parte delle "cifre significative", ma a-bsarà sempre diverso da zero e avrà il segno giusto per a! = B.
Peter Cordes,

4

per gestire undefined, null e NaN: Null si comporta come 0, NaN e undefined va a finire.

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]

3

Solo per una normale matrice di valori di elementi:

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]**

Per una matrice di oggetti:

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}]**

2

Aggiornare! Scorri fino alla fine della risposta per l' smartSortadditivo prop che ti dà ancora più divertimento!
Ordina le matrici di qualsiasi cosa !

La mia forma preferita personale di questa funzione consente un parametro per Ascendente o Discendente:

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)
    }
};

Utilizzo semplice come:

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


O esempio di frammento di codice qui!

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')

Ora divertiti ancora di più con un metodo di ordinamento che ordina un array pieno di più elementi! Attualmente non copre "associativo" (ovvero chiavi di stringa), ma copre ogni tipo di valore! Non solo ordinerà i valori multipli asco di descconseguenza, ma manterrà anche la "posizione" costante di "gruppi" di valori. In altre parole; gli interi sono sempre i primi, poi le stringhe, quindi le matrici (sì, lo sto facendo in modo multidimensionale!), quindi gli Oggetti (non filtrato, elemento, data) e infine indefiniti e nulli!

"Perché?" tu chiedi. Perchè no!

Ora arriva in 2 gusti! Il primo dei quali richiede browser più recenti in quanto utilizza Object.definePropertyper aggiungere il metodo Array.protoypeall'oggetto. Questo permette per la facilità d' naturali uso, come ad esempio: myArray.smartSort('a'). Se devi implementare per browser meno recenti o semplicemente non ti piace modificare gli oggetti nativi, scorri verso il basso fino alla versione Solo metodo .

/* 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'uso è semplice! Per prima cosa crea un array folle come:

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' });

Quindi ordinalo semplicemente!

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

Solo metodo

Come il precedente, ad eccezione di un semplice metodo!

/* 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 */

Uso:

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

Metodo jsFiddle smartSort (Array, "asc | desc")


2

Prova questo codice:

HTML:

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

Codice 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>

2

Prova questo codice come di seguito

var a = [5, 17, 29, 48, 64, 21];
function sortA(arr) {
return arr.sort(function(a, b) {
return a - b;
})
;} 
alert(sortA(a));

non è vero?
user7125929,

1
var numArray = [140000, 104, 99];
numArray = numArray.sort((a,b) => a-b);
alert(numArray)

4
Benvenuto in StackOverflow. La tua risposta è identica alla risposta accettata. Puoi aggiungere qualche spiegazione alla tua risposta per dire perché questo dovrebbe essere preferito rispetto alla risposta accettata?
Semplicemente arrivato

1

Sebbene non sia richiesto in JavaScript, se si desidera che restituisca rigorosamente -1, 0 o 1 (simile a come funziona l' operatore di astronave in PHP), è possibile utilizzare .sort() compareFunctionMath.sign()

Quanto compareFunctionsegue restituisce rigorosamente -1, 0 o 1:

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

Nota: Math.sign() non è supportato in Internet Explorer.


0

Questa è la soluzione già proposta e accettata come metodo sul prototipo di array:

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

0

Come metodo di ordinamento converte gli elementi dell'array in stringa. Quindi, di seguito funziona bene anche con numeri decimali con elementi di matrice.

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

E ti dà il risultato atteso.


0

Sostituzione del metodo di ordinamento.

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]

0

La funzione di ordinamento predefinita è l'ordinamento nell'ordine del dizionario:

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

Quello sopra non è il caso che vogliamo per i numeri. Quindi se hai numeri interi e la funzione di ordinamento predefinita non funziona (perché si ordina in ordine di dizionario), allora devi implementare la tua funzione:

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]

Spero che tu abbia una domanda in mente come funziona? Qui quando forniamo un metodo nella funzione di ordinamento, passa due numeri ogni volta e se il numero ritorna

  • -ve valore o 0, mantiene il primo numero al suo posto
  • + ve lo valore scambia il posto.

Seguendo questo per tutti i numeri, ordina la matrice di numeri interi.

Se si utilizza ES6, scrivere una funzione freccia:

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

-1

Ecco la mia funzione di array di ordinamento nella libreria 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]

3
Questo è assolutamente sbagliato! la funzione di ordinamento deve restituire numeri negativi, 0 o positivi, non vero o falso.
jperelli,

Come ha detto @jperelli, la funzione di ordinamento ha bisogno di un numero, non di un valore booleano, per essere restituito (e dato come ci sono 3 stati possibili, uguali, sopra e sotto, questo è necessario per avere un ordinamento stabile). Come viene indicata la tua risposta, non funziona. a-bdovrebbe essere usato invece. (Puoi avere fantasia e fare un Number(a>b)-0.5, tuttavia non è ancora un ordinamento stabile).
ecc521
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.