Как правильно отсортировать массив целых чисел


850

Попытка получить самое высокое и самое низкое значение из массива, который, как я знаю, будет содержать только целые числа, кажется труднее, чем я думал.

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

Я ожидаю, что это покажет 99, 104, 140000. Вместо этого это показывает 104, 140000, 99. Так что, похоже, сортировка обрабатывает значения как строки.

Есть ли способ заставить функцию сортировки фактически сортировать по целому значению?


10
Обратите внимание, что ни один из лучших ответов правильно не обрабатывает все значения с плавающей точкой; в частности, никто из них не справляется NaN. Было бы неплохо увидеть высокопоставленный ответ, который касается NaN.
Quuxplusone

3
Кстати, если вы сортируете много и много целых чисел, будет полезно использовать алгоритм целочисленной сортировки, такой как счетная сортировка . Сортировка по времени займет линейное масштабирование с размером вашего массива: O (n). Принимая во внимание, что все решения здесь используют сортировку сравнения, которая менее эффективна: O (n * log n).
Web_Designer

1
@Web_Designer Счетная сортировка является линейной относительно диапазона чисел, а не массива. Например, сортировка [1,1000000] займет более 2 шагов, так как алгоритм должен будет сканировать каждый индекс массива в диапазоне от 1 до 1000000, чтобы увидеть, какое значение ячейки больше 0.
18-18

2
@yters Используя хэш-карту, вы можете обращать внимание только на целые числа, которые отображаются в отсортированном массиве. Это делает сортировку линейной по размеру массива.
Кевин

1
самый быстрый способ - использовать модуль изоморфного массива сортировки, который изначально работает как в браузере, так и в узле, поддерживая любой тип ввода, вычисляемые поля и пользовательские порядки сортировки.
Ллойд

Ответы:


1236

По умолчанию метод сортировки сортирует элементы по алфавиту. Для числовой сортировки просто добавьте новый метод, который обрабатывает числовые сортировки (sortNumber, показанный ниже) -

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

console.log(numArray);

В ES6 вы можете упростить это с помощью функций стрелок:

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

Документация:

Mozilla Array.prototype.sort()рекомендует эту функцию сравнения для массивов, которые не содержат Infinity или NaN. (Потому что Inf - Infэто NaN, а не 0).

Также приведены примеры сортировки объектов по ключу.


149
Ницца. Но действительно ли нет никакого готового способа получить числовую сортировку из javascript?
peirix

39
ахах это из коробки! Но если вы действительно непрактичны, вы можете связать функции с классом массива в самом начале вашего JavaScript: // Array.prototype.sortNormal = function () {return this.sort (function (a, b) {return a - b})} // Теперь вызов .sortNormal () для любого массива отсортирует его численно
Джек Франзен

13
Почему а, а не а> б. Я предлагаю последний, чтобы избежать ошибок в работе машины
Luca Davanzo

35
@Velthune Функция сравнения должна возвращать -1, 0 или +1. a> b вернет только true или false.
Иван Перес

48
Этот код можно сократить, используя функцию стрелки . numberArray.sort((a, b) => (a - b));Ура! Я думаю, что это близко к стандартному способу. Примечание: проверьте, поддерживает ли ваш движок JS функции стрелок.
Константин Ван

174

Просто опираясь на все приведенные выше ответы, они также могут быть выполнены в одну строку, например:

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 Исправлено: var arr = [140000, 104, 99].sort(function(a,b) { return a-b; });. Или более компактно, в ES6let arr = [140000, 104, 99].sort((a,b) => a-b);
00500005

1
Как я сказал в комментарии выше, функции стрелок здесь плохо подходят, и я бы никому не рекомендовал использовать их таким образом. Вы используете побочный эффект синтаксиса стрелки, чтобы вырезать слова functionи return, но на самом деле не используете истинную цель передачи функции стрелки this. Этот код подразумевает, что thisпроисходит передача контекста, но это не так. Запутывает других разработчиков, чтобы прочитать ваш код, просто чтобы сохранить несколько символов. Не зависит от побочных эффектов - код с целью!
бамберство

12
@bambery Я не думаю, что вам нужно использовать функцию стрелки исключительно для изменения контекста ...
Тед Морин

7
@bambery, вы на самом деле неправильно понимаете, что делает функция стрелки. Вы думаете, что это как-то переходит thisв функцию, но это не так. На самом деле он игнорирует создание переменных a thisи, argumentsкоторые обычно перезаписывают родительские переменные. Единственная причина, которую вы можете использовать thisвнутри функции стрелки - это лексическая область видимости.
17

2
@bambery, который не очень хорошо стареет ... три года спустя и современная разработка javascript использует функции стрелок почти исключительно. :)
Кип

71

array.sort выполняет лексикографическую сортировку по умолчанию, для числовой сортировки предоставляет собственную функцию. Вот простой пример:

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

numArray.sort(compareNumbers);

Также обратите внимание, что сортировка работает «на месте», нет необходимости в назначении.


Я не понял код выше, как «возвращает a - b» сортировка по возрастанию?
vikramvi

если a <b, compareNumbers возвращает отрицательное число. Если a> b, это будет положительно. Если равно, возвращается 0.
Пол Диксон

38

Этот ответ эквивалентен некоторым из существующих ответов, но функции стрелок ECMAScript 6 предоставляют гораздо более компактный синтаксис, который позволяет нам определять встроенную функцию сортировки, не жертвуя удобочитаемостью:

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

Это поддерживается в большинстве браузеров сегодня .


1
«без ущерба для читаемости». Это субъективно. С некоторыми простыми числами это читается. При работе со сложными объектами вы хотите отсортировать по свойству не так уж много.
Тристан

3
@Tristan, сортировка по свойству объекта все еще может быть выполнена довольно чисто с использованием этого синтаксиса. Если свойство объекта, по которому вы хотите отсортировать, - это число, которое вы можете сделать: objArray=objArray.sort((a,b)=>a.numProperty - b.numProperty);и если свойство является строкой, которую вы можете сделать: objArray=objArray.sort((a,b)=>a.strProperty.localeCompare(b.strProperty))‌​;сказанное выше, этот вопрос специально задает вопрос о сортировке массива целых чисел
jjjjs

34

Я удивлен, почему все рекомендуют передавать функцию сравнения sort(), которая делает сортировку очень медленной!

Чтобы отсортировать числа, просто создайте любой TypedArray :

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


4
Использование TypedArray ускоряет сортировку примерно в 5 раз. Если вы хотите работать еще быстрее, hpc-алгоритмы в пакете npm реализованы Radix Sort и Counting Sort, которые предлагают несколько ответов.
DragonSpit

вау, не знал, что это существовало!
pixelearth

21

Причина, почему функция сортировки ведет себя так странно

Из документации :

[...] массив сортируется в соответствии со значением кодовой точки Unicode каждого символа в соответствии с преобразованием строки каждого элемента.

Если вы распечатаете значения точек Unicode в массиве, это станет ясно.

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

Возвращает: «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)

Теперь, поскольку 140000 и 104 вернули одинаковые значения (49), он обрезает первый индекс и проверяет снова:

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)

Если мы отсортируем это, то получим:

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

поэтому 104 идет раньше 140000.

Итак, окончательный результат будет:

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

104, 140000, 99

Вывод:

sort() выполняет сортировку, просматривая только первый индекс чисел. sort()не заботится о том, что целое число больше другого, оно сравнивает значение юникода цифр, а если есть два равных значения юникода, то проверяет, есть ли следующая цифра, и сравнивает ее.

Для правильной сортировки вы должны передать функцию сравнения, sort()как описано здесь .


Подсказка: это только мое объяснение, я на самом деле не искал код. Так что не стоит полностью доверять этому ответу.
Черный

17

Я согласен с Акс, но вместо того, чтобы использовать

return a - b;

Вы должны использовать

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

18
Можете ли вы объяснить, почему кто-то должен использовать вашу более нечитаемую троичную операцию? Насколько я могу сказать, это будет иметь тот же результат.
stefannew

6
Этот ответ также учитывает равные значения и оставляет их в одном месте.
Maarten00

23
А а - б нет?
Брайан Рэйнер

12
«return ab» может быть адекватным для конкретного случая этого вопроса (javascript и всех элементов ввода, которые известны как целые), но лично я предпочитаю троичную форму, потому что она более каноническая - она ​​работает в большем количестве случаев, в большем количестве языков программирования , с большим количеством типов данных. Например, в C ab может переполниться, что приведет к бесконечному циклу сортировки, повреждению памяти, падению и т. Д. При этом даже троичная форма не будет работать нормально, если задействованы NaN или смешанные типы.
Дон Хэтч

8
>И <еще сравнить а и Ь в виде строк.
vriesdemichael

11

В новом мире ES6 гораздо проще сделать

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

Это все, что вам нужно :)


10

В JavaScript поведение метода sort () по умолчанию заключается в сортировке значений в массиве по алфавиту.

Для сортировки по номеру необходимо определить числовую функцию сортировки (что очень просто):

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

numArray = numArray.sort(sortNumber);

8

Array.prototype.sort () - это метод go to для сортировки массивов, но нам нужно знать о нескольких проблемах.

Порядок сортировки по умолчанию лексикографический, а не числовой, независимо от типов значений в массиве. Даже если массив состоит из всех чисел, все значения будут преобразованы в строку и отсортированы лексикографически.

Поэтому нам нужно настроить метод sort () и reverse (), как показано ниже.

Ссылочный URL

Для сортировки чисел внутри массива

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

Для изменения чисел внутри массива

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

Ссылочный URL


6

На вопрос уже дан ответ, самый короткий путь - это использование sort()метода. Но если вы ищете дополнительные способы сортировки массива чисел, а также любите циклы, проверьте следующее

Вид вставки

Восходящий:

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

По убыванию:

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

Сортировка выбора:

Восходящий:

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

По убыванию:

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

Радоваться, веселиться


Являются ли какие-либо из них на самом деле более быстрыми для крошечных массивов, чем использование sort()TypedArray, как предполагает этот ответ . Конечно, они не будут быстрее для средних и больших массивов, потому что это O (n ^ 2) алгоритмы.
Питер Кордес

5

Функция «численно», приведенная ниже, служит для сортировки массива чисел во многих случаях, когда она предоставляется в качестве функции обратного вызова:

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

array.sort(numerically); 

Но в некоторых редких случаях, когда массив содержит очень большие и отрицательные числа, может возникнуть ошибка переполнения, поскольку в результате значение ab становится меньше наименьшего числа, с которым может справиться JavaScript.

Итак, лучший способ написания числовой функции заключается в следующем:

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

1
JavaScript числа с плавающей точкой. IEEE754 определяет правила переполнения и переполнения, включая переполнение до + -Infinity и понижение до субнормального или + -0.0. Я не думаю, что вычитание двух чисел может опуститься до + -0,0, даже если они оба большие и близкие равны. Разница между двумя двойными значениями всегда представляется в виде другого ненулевого двойного значения (если только оно не переполняется DBL_MIN - DBL_MAX), но возможное снижение значения невозможно. Катастрофическое аннулирование делает результат неточным, теряя большинство его «значащих цифр», но a-bвсегда будет отличным от нуля и будет иметь правильный знак a! = B.
Питер Кордес

4

для обработки неопределенных, нулевых и NaN: Null ведет себя как 0, NaN и неопределенные идут до конца.

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

Только для обычного массива значений элементов:

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

Для массива объектов:

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

Обновить! Прокрутите до нижней части ответа, чтобы smartSortдобавить добавку, которая доставит вам еще больше удовольствия!
Сортирует массивы чего угодно !

Моя личная любимая форма этой функции позволяет использовать параметр Ascending или Descending:

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

Использование так просто, как:

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


Или пример фрагмента кода здесь!

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

Теперь получайте еще больше удовольствия от метода сортировки, который сортирует массив, состоящий из нескольких элементов! В настоящее время не охватывает «ассоциативный» (иначе, строковые ключи), но он охватывает практически все типы значений! Он не только будет сортировать несколько значений ascили, descсоответственно, но также будет поддерживать постоянную «позицию» «групп» значений. Другими словами; сначала идут int, затем идут строки, затем массивы (да, я делаю это многомерным!), затем объекты (нефильтрованные, элемент, дата) и, наконец, неопределенные и нулевые!

"Почему?" ты спрашиваешь. Почему бы нет!

Теперь поставляется в 2 вкусах! Первый из них требует более новых браузеров, поскольку он использует Object.definePropertyдля добавления метода к Array.protoypeобъекту. Это позволяет упростить естественное использование, такие как: myArray.smartSort('a'). Если вам нужно реализовать для старых браузеров, или вам просто не нравится модифицировать нативные объекты, прокрутите вниз до версии Method Only .

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


Использовать просто! Сначала создайте какой-нибудь сумасшедший массив вроде:

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

Тогда просто сортируйте это!

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

Только метод

То же, что и предыдущий, за исключением простого метода!

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

Использование:

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

Метод jsFiddle smartSort (Массив, "asc | desc")


2

Попробуйте этот код:

HTML:

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

Код 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

Попробуйте этот код, как показано ниже

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

не правда ли?
user7125929

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

4
Добро пожаловать в StackOverflow. Ваш ответ идентичен принятому ответу. Можете ли вы добавить какое-либо объяснение к вашему ответу, чтобы сказать, почему это должно быть предпочтительнее, чем принятый ответ?
Просто Гед

1

Хотя это не требуется в JavaScript, если вы хотите, чтобы он строго возвращал -1, 0 или 1 (аналогично тому, как работает оператор космического корабля в PHP), вы можете использовать его .sort() compareFunctionMath.sign()

compareFunctionНиже строго возвращает -1, 0 или 1:

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

Примечание: Math.sign() не поддерживается в Internet Explorer.


0

Это уже предложенное и принятое решение в качестве метода на прототипе Array:

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

0

Метод сортировки преобразует элементы массива в строку. Таким образом, ниже путь также отлично работает с десятичными числами с элементами массива.

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

И дает вам ожидаемый результат.


0

Переопределение метода сортировки.

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

Функция сортировки по умолчанию - сортировка в словаре:

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

Вышеупомянутый случай не тот, который мы хотим для чисел. Так что если у вас есть целые числа и функция сортировки по умолчанию не работает (потому что она сортируется в словаре), то вам нужно реализовать свою собственную функцию:

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]

Я надеюсь, у вас есть вопрос, как это работает? Здесь, когда мы предоставляем метод в функции сортировки, он передает два числа каждый раз, и если число возвращает

  • -ve значение или 0, он сохраняет первое число на своем месте
  • + мы ценим это место обмена.

Следуя этому для всех чисел, он сортирует массив целых чисел.

Если вы используете ES6, напишите функцию стрелки:

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

-1

Вот моя функция сортировки в библиотеке 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
Это совершенно неправильно! Функция сортировки должна возвращать отрицательные, 0 или положительные числа, а не true или false.
Джерелли

Как уже упоминалось в @jperelli, функции сортировки нужно вернуть число, а не логическое значение (и учитывая, что существует 3 возможных состояния: равное, выше и ниже, это необходимо для стабильной сортировки). Как говорится в вашем ответе, он не работает. a-bследует использовать вместо (Вы можете придумать и сделать Number(a>b)-0.5, но это все еще не стабильный вид).
ecc521
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.