Jak poprawnie posortować tablicę liczb całkowitych

846

Próba uzyskania najwyższej i najniższej wartości z tablicy, która, jak wiem, będzie zawierać tylko liczby całkowite, wydaje się trudniejsza niż myślałem.

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

Spodziewałbym się tego 99, 104, 140000. Zamiast tego pokazuje 104, 140000, 99. Wygląda więc na to, że sort obsługuje wartości jako ciągi znaków.

Czy istnieje sposób, aby funkcja sortowania faktycznie sortowała według wartości liczb całkowitych?

peirix
źródło
10
Zauważ, że żadna z najlepszych odpowiedzi nie obsługuje poprawnie wszystkich wartości zmiennoprzecinkowych; w szczególności żaden z nich nie obsługuje NaN. Byłoby miło zobaczyć wysoko ocenianą odpowiedź, która dotyczy NaN.
Quuxplusone
3
BTW, jeśli sortujesz wiele liczb całkowitych, korzystne będzie użycie algorytmu sortowania liczb całkowitych, takiego jak sortowanie zliczania . Sortowanie według czasu potrwa, aby uruchomić skale liniowo z rozmiarem tablicy: O (n). Podczas gdy wszystkie rozwiązania wykorzystują sortowanie porównawcze, które jest mniej wydajne: O (n * log n).
Web_Designer
1
@Web_Designer Sortowanie liczenia jest liniowe w odniesieniu do zakresu liczb, a nie tablicy. Na przykład sortowanie [1 1000000] zajmie więcej niż 2 kroki, ponieważ algorytm będzie musiał przeskanować każdy indeks tablicy od 1 do 1000000, aby zobaczyć, która wartość komórki jest większa niż 0.
od
2
@yters Za pomocą mapy skrótów można zwracać uwagę tylko na liczby całkowite wyświetlane w sortowanej tablicy. To sprawia, że ​​sortowanie liniowe wrt do rozmiaru tablicy.
Kevin
1
najszybszym sposobem jest użycie izomorficznego modułu macierzy sortowania , który działa natywnie zarówno w przeglądarce, jak i w węźle, obsługując dowolny typ danych wejściowych, pól obliczeniowych i niestandardowe porządki sortowania.
Lloyd

Odpowiedzi:

1233

Domyślnie metoda sortowania sortuje elementy alfabetycznie. Aby posortować numerycznie, po prostu dodaj nową metodę, która obsługuje sortowanie numeryczne (sortNumber, pokazano poniżej) -

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

console.log(numArray);

W ES6 możesz to uprościć za pomocą funkcji strzałek:

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

Dokumentacja:

Mozilla Array.prototype.sort()zaleca tę funkcję porównywania dla tablic, które nie zawierają Infinity ani NaN. (Ponieważ Inf - Infjest NaN, a nie 0).

Również przykłady sortowania obiektów według klucza.

aks
źródło
147
Miły. Ale czy naprawdę nie ma gotowego sposobu na uzyskanie sortowania numerycznego z javascript?
peirix
39
ach, to jest gotowe! Ale jeśli jesteś naprawdę niepraktyczny, możesz powiązać funkcje z klasą klasy tablicowej na samym początku javascript: // Array.prototype.sortNormal = function () {return this.sort (function (a, b) {return a - b})} // Teraz wywołanie .sortNormal () na dowolnej tablicy posortuje ją numerycznie
Jack Franzen
13
Dlaczego ab, a nie a> b. Proponuję ostatni, aby uniknąć błędów maszyny podczas operacji
Luca Davanzo
35
@Velthune Funkcja porównania powinna zwracać -1, 0 lub +1. a> b zwróci tylko true lub false.
Iván Pérez
48
Ten kod można skrócić za pomocą funkcji strzałki . numberArray.sort((a, b) => (a - b));Tak! Myślę, że jest to bliskie out-of-the-box sposób. Uwaga: sprawdź, czy silnik JS obsługuje funkcje strzałek.
Константин Ван
173

Opierając się na wszystkich powyższych odpowiedziach, można je również wykonać w jednym wierszu:

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
źródło
8
@bodyflex Poprawiono: var arr = [140000, 104, 99].sort(function(a,b) { return a-b; });. Lub bardziej kompaktowy, w ES6let arr = [140000, 104, 99].sort((a,b) => a-b);
00500005
1
Jak powiedziałem w powyższym komentarzu, funkcje strzałek nie pasują tutaj i odradzam każdemu korzystanie z nich w ten sposób. Używasz efektu ubocznego składni strzałki do wycinania słów functioni return, ale tak naprawdę nie używasz prawdziwego celu przejścia przez funkcję strzałki this. Ten kod sugeruje, że zdarza się pewne thisprzekazywanie kontekstu, ale tak nie jest. Mylące dla innych programistów, aby odczytać twój kod, tylko po to, aby zapisać kilka znaków. Nie polegaj na skutkach ubocznych - koduj celowo!
bambery
12
@ bambery Nie sądzę, że musisz używać funkcji strzałki wyłącznie do zmiany kontekstu ...
Ted Morin
7
@ambery, naprawdę źle rozumiesz, co robi funkcja strzałki. Myślisz, że jakoś przechodzi thisdo funkcji, ale to nieprawda. W rzeczywistości zaniedbuje się tworzenie zmiennej thisi oraz, argumentsktóra zwykle zastępuje zmienne nadrzędne. Jedynym powodem, dla którego można użyć thisfunkcji strzałki, jest zakres leksykalny.
cuth
2
@ambambery, które nie zestarzały się dobrze ... trzy lata później i współczesne tworzenie javascript używa prawie wyłącznie strzałek. :)
Kip
71

array.sort domyślnie wykonuje sortowanie leksykograficzne, dla sortowania numerycznego podaj własną funkcję. Oto prosty przykład:

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

numArray.sort(compareNumbers);

Pamiętaj też, że sortowanie działa „na miejscu”, nie ma potrzeby przypisywania.

Paul Dixon
źródło
Nie zrozumiałem powyższego kodu, w jaki sposób „return a - b” wykonuje sortowanie rosnąco?
vikramvi
jeśli a <b, CompareNumbers zwraca liczbę ujemną. Jeśli a> b, będzie dodatni. Jeśli jest równy, zwraca 0.
Paul Dixon
38

Ta odpowiedź jest równoważna z niektórymi istniejącymi odpowiedziami, ale funkcje strzałek ECMAScript 6 zapewniają znacznie bardziej kompaktową składnię, która pozwala nam zdefiniować wbudowaną funkcję sortowania bez poświęcania czytelności:

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

Jest obecnie obsługiwany w większości przeglądarek .

jjjjs
źródło
1
„bez poświęcania czytelności”. To jest subiektywne. Niektóre proste liczby całkowite są czytelne. Podczas pracy z bardziej złożonymi obiektami i chcesz sortować według właściwości, nie tyle.
Tristan
3
@ Tristan, sortowanie według właściwości obiektu nadal może być dość czyste przy użyciu tej składni. Jeśli właściwość obiektu, który chcesz posortować, to liczba, którą możesz zrobić: objArray=objArray.sort((a,b)=>a.numProperty - b.numProperty);a jeśli właściwość jest ciągiem, możesz: objArray=objArray.sort((a,b)=>a.strProperty.localeCompare(b.strProperty))‌​;To powiedziawszy, to pytanie konkretnie dotyczy sortowania tablicy liczb całkowitych
jjjjs
34

Jestem zaskoczony, dlaczego wszyscy zalecają przekazanie funkcji porównawczej sort(), która sprawia, że ​​sortowanie jest naprawdę wolne!

Aby posortować liczby, po prostu utwórz dowolny TypedArray :

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

dy_
źródło
4
Użycie TypedArray przyspiesza sortowanie o około 5X. Jeśli chcesz iść jeszcze szybciej, np. Pakiet hpm-algorytmy implementuje Radix Sort and Counting Sort, co sugeruje kilka odpowiedzi tutaj.
DragonSpit,
wow, nie wiedziałem, że to istnieje!
pixelearth
21

Powód, dla którego funkcja sortowania zachowuje się tak dziwnie

Z dokumentacji :

[...] tablica jest sortowana według wartości punktowej kodu każdego znaku Unicode, zgodnie z konwersją łańcucha każdego elementu.

Jeśli wydrukujesz wartości punktu Unicode tablicy, to się wyczyści.

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

Zwraca: „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)

Teraz, ponieważ 140000 i 104 zwróciły te same wartości (49), odcina pierwszy indeks i sprawdza ponownie:

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)

Jeśli to posortujemy, otrzymamy:

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

więc 104 występuje przed 140000.

Tak więc końcowy wynik będzie:

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

104, 140000, 99

Wniosek:

sort()sortuje, patrząc tylko na pierwszy indeks liczb. sort()nie dba o to, czy liczba całkowita jest większa od innej, porównuje wartość Unicode cyfr, a jeśli istnieją dwie równe wartości Unicode, sprawdza, czy jest następna cyfra, i porównuje ją.

Aby sortować poprawnie, musisz przekazać funkcję porównania, sort()tak jak to wyjaśniono tutaj .

czarny
źródło
Wskazówka: to tylko moje wyjaśnienie, tak naprawdę nie sprawdziłem kodu. Więc nie ufaj w pełni tej odpowiedzi.
Czarny
17

Zgadzam się z aks, jednak zamiast używać

return a - b;

Powinieneś użyć

return a > b ? 1 : a < b ? -1 : 0;
użytkownik3587638
źródło
18
Czy potrafisz wyjaśnić, dlaczego ktokolwiek powinien skorzystać z bardziej nieczytelnej operacji trójskładnikowej? O ile mogę powiedzieć, miałoby to ten sam rezultat.
stefannew
6
Ta odpowiedź uwzględnia równe wartości i pozostawia je w tym samym miejscu.
Maarten00
23
A a - b nie?
Bryan Rayner,
12
„return ab” może być odpowiednie dla konkretnego przypadku tego pytania (javascript i wszystkie elementy wejściowe znane jako ints), ale osobiście wolę formę trójskładnikową, ponieważ jest bardziej kanoniczna - działa w większej liczbie przypadków, w większej liczbie języków programowania , z większą liczbą typów danych. Np. W C ab może się przepełnić, co prowadzi do sortowania nieskończonego zapętlania, niszczenia pamięci, awarii itp. To powiedziawszy, nawet trójskładnik nie będzie działał zdrowo, jeśli w grę wchodzą NaN lub typy mieszane.
Don Hatch,
8
>I <nadal porównać A i B ciągów.
vriesdemichael
11

W nowym świecie ES6 łatwiej jest coś takiego zrobić

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

To wszystko czego potrzebujesz :)

Chait
źródło
10

W JavaScript domyślnym zachowaniem metody sort () jest sortowanie wartości w tablicy alfabetycznie.

Aby posortować według numeru, musisz zdefiniować funkcję sortowania numerycznego (co jest bardzo łatwe):

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

numArray = numArray.sort(sortNumber);
Peter Mortensen
źródło
8

Array.prototype.sort () to metoda sortowania tablic, ale należy pamiętać o kilku kwestiach.

Kolejność sortowania jest domyślnie leksykograficzna, a nie numeryczna, niezależnie od typów wartości w tablicy. Nawet jeśli tablica zawiera wszystkie liczby, wszystkie wartości zostaną przekonwertowane na ciąg i posortowane leksykograficznie.

Powinniśmy więc dostosować metodę sort () i reverse () jak poniżej.

Polecony adres URL

Do sortowania liczb w tablicy

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

Do cofania liczb w tablicy

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

Polecony adres URL

Merbin Joe
źródło
6

Na pytanie już udzielono odpowiedzi, najkrótszą metodą jest użycie sort()metody. Ale jeśli szukasz więcej sposobów na posortowanie tablicy liczb i lubisz cykle, sprawdź poniższe

Sortowanie przez wstawianie

Rosnąco:

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

Malejąco:

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

Sortuj wybór:

Rosnąco:

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

Malejąco:

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

baw się dobrze

Komercyjne samobójstwo
źródło
Czy którekolwiek z nich są rzeczywiście szybsze dla małych tablic niż używanie sort()na TypedArray, jak sugeruje ta odpowiedź . Z pewnością nie będą one szybsze dla średnich i dużych tablic, ponieważ są to algorytmy O (n ^ 2).
Peter Cordes,
5

Funkcja „numerycznie” poniżej służy do sortowania tablic liczb w wielu przypadkach, gdy jest udostępniana jako funkcja zwrotna:

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

array.sort(numerically); 

Ale w niektórych rzadkich przypadkach, gdy tablica zawiera bardzo duże i ujemne liczby, może wystąpić błąd przepełnienia, ponieważ wynik ab staje się mniejszy niż najmniejsza liczba, z którą JavaScript może sobie poradzić.

Tak więc lepszy sposób pisania funkcji numerycznej jest następujący:

function numerically(a, b){
   if(a < b){
      return -1;
   } else if(a > b){
      return 1;
   } else {
      return 0;
   }
}
leet101
źródło
1
Numery JavaScript są zmiennoprzecinkowe. IEEE754 definiuje reguły przepełnienia i niedopełnienia, w tym przepełnienie do + -Infinity i niedopełnienie do wartości nienormalnych lub + -0,0. Nie sądzę, aby odjęcie dwóch liczb mogło spaść poniżej +0,0, nawet jeśli są duże i równe w pobliżu. Różnica między dwoma podwójnymi jest zawsze reprezentowana jako kolejne niezerowe podwójne (chyba że się przepełnia, jak DBL_MIN - DBL_MAX), ale niedopełnienie nie jest możliwe. Katastrofalne anulowanie powoduje, że wynik jest nieprecyzyjny, tracąc większość „znaczących cyfr”, ale a-bzawsze będzie niezerowy i będzie miał odpowiedni znak dla a! = B.
Peter Cordes,
4

do obsługi niezdefiniowanych, zerowych i NaN: Null zachowuje się jak 0, NaN i niezdefiniowane kończy się.

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
źródło
3

Tylko dla normalnej tablicy wartości elementów:

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

W przypadku tablicy obiektów:

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
źródło
2

Aktualizacja! Przewiń do dołu odpowiedzi, aby znaleźć smartSortdodatek, który zapewni jeszcze więcej zabawy!
Sortuje tablice czegokolwiek !

Moja osobista ulubiona forma tej funkcji pozwala na określenie parametru Rosnąco lub Malejąco:

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

Użycie tak proste jak:

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


Lub przykładowy fragment kodu tutaj!

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

Teraz baw się jeszcze lepiej dzięki metodzie sortowania, która sortuje tablicę pełną wielu przedmiotów! Obecnie nie obejmuje „asocjacyjnego” (aka, ciągów znaków), ale obejmuje wszystkie wartości! Nie tylko posortuje wiele wartości asclub descodpowiednio, ale także utrzyma stałą „pozycję” „grup” wartości. Innymi słowy; ints są zawsze pierwsze, potem łańcuchy, potem tablice (tak, robię to wielowymiarowe!), następnie Obiekty (niefiltrowane, element, data), a na koniec niezdefiniowane i zerowe!

"Dlaczego?" ty pytasz. Dlaczego nie!

Teraz występuje w 2 smakach! Pierwsza z nich wymaga nowszych przeglądarek, ponieważ używa Object.definePropertymetody dodawania metody do Array.protoypeobiektu. Pozwala to na łatwość naturalnego użytkowania, takich jak: myArray.smartSort('a'). Jeśli chcesz zaimplementować starsze przeglądarki lub po prostu nie lubisz modyfikować obiektów natywnych, przewiń w dół do wersji Tylko metoda .

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


Użycie jest proste! Najpierw utwórz szaloną tablicę, taką jak:

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

Następnie posortuj to!

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

Tylko metoda

Taki sam jak poprzedni, tyle że tylko prosta metoda!

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

Posługiwać się:

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

jsFiddle Method smartSort (Array, „asc | desc”)

SpYk3HH
źródło
2

Wypróbuj ten kod:

HTML:

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

Kod 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
źródło
2

Wypróbuj ten kod jak poniżej

var a = [5, 17, 29, 48, 64, 21];
function sortA(arr) {
return arr.sort(function(a, b) {
return a - b;
})
;} 
alert(sortA(a));
użytkownik7125929
źródło
czy to nie prawda?
user7125929,
1
var numArray = [140000, 104, 99];
numArray = numArray.sort((a,b) => a-b);
alert(numArray)
Vardaman PK
źródło
4
Witamy w StackOverflow. Twoja odpowiedź jest identyczna z odpowiedzią zaakceptowaną. Czy możesz dodać jakieś wyjaśnienie do swojej odpowiedzi, aby powiedzieć, dlaczego powinno być to lepsze niż odpowiedź zaakceptowana?
Po prostu Ged
1

Chociaż nie jest to wymagane w JavaScript, jeśli chcesz ściśle zwracać -1, 0 lub 1 (podobnie jak operator statku kosmicznego w PHP), możesz użyć .sort() compareFunctionMath.sign()

compareFunctionPoniżej ściśle zwraca -1, 0, lub 1:

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

Uwaga: Math.sign() nie jest obsługiwany w przeglądarce Internet Explorer.

Grant Miller
źródło
0

To jest już zaproponowane i zaakceptowane rozwiązanie jako metoda na prototypie Array:

Array.prototype.sortNumeric = function () {
    return this.sort((a, b) => a - b);
};
Array.prototype.sortNumericDesc = function () {
    return this.sort((a, b) => b - a);
};
Błąd 404
źródło
0

Metoda sortowania konwertuje elementy tablicy na ciąg znaków. Tak więc poniżej sposób działa również dobrze z liczbami dziesiętnymi z elementami tablicy.

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

I daje oczekiwany wynik.

Anshul Chaurasia
źródło
0

Przesłanianie metody sortowania.

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
źródło
0

Domyślną funkcją sortowania jest sortowanie w kolejności słownikowej:

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

Powyższy nie dotyczy liczb. Więc jeśli masz liczby całkowite i domyślna funkcja sortowania nie działa (ponieważ sortuje w kolejności słownikowej), musisz zaimplementować własną funkcję:

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]

Mam nadzieję, że masz na uwadze pytanie, jak to działa? Tutaj, gdy zapewniamy metodę w funkcji sortowania, przekazuje dwie liczby za każdym razem i jeśli liczba zwraca

  • -ve wartość lub 0, utrzymuje pierwszą liczbę na swoim miejscu
  • + ve wartość to zamiana miejsca.

Postępując zgodnie z tym dla wszystkich liczb, sortuje tablicę liczb całkowitych.

Jeśli używasz ES6, napisz funkcję strzałki:

console.log(ar.sort((num1,num2)=> num1-num2));
    //it will sort like :=> [3, 200, 10000]
JustIn
źródło
-1

Oto moja funkcja tablicy sortowania w bibliotece 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]
pożar
źródło
3
To jest po prostu źle! funkcja sortowania musi zwracać liczby ujemne, 0 lub dodatnie, nieprawdziwe lub fałszywe.
jperelli,
Jak wspomniał @jperelli, funkcja sortowania wymaga zwrotu liczby, a nie logicznej (i biorąc pod uwagę, że istnieją 3 możliwe stany, równe, powyżej i poniżej, jest to konieczne, aby mieć stabilne sortowanie). Jak podano w odpowiedzi, nie działa. a-bnależy zamiast tego użyć. (Możesz się przyzwyczaić i zrobić Number(a>b)-0.5, ale to wciąż nie jest stabilny rodzaj).
ecc521,