Теперь я не понял, почему это происходит, и кто-нибудь может рассказать подробно о том, какой тип алгоритма используется в этой функции sort()? Это потому, что для любого другого языка я не нашел эту проблему, когда функция не правильно сортировала числа.
Любая помощь очень ценится.
Ответ 2
Чтобы ответить на вопрос о том, как работает функция сортировки, я подробно объясню это. Как было сказано в большинстве ответов здесь, вызов только sort()
в массиве будет сортировать ваш массив с помощью строк. Преобразование целых чисел в строки. Blech!
Если вы думаете о своих товарах как о символах, а не о цифрах, имеет смысл, что он будет отсортирован таким образом. Хороший способ увидеть это - назначить буквы вашим номерам.
//0 = a
//1 = b
//2 = c
//4 = e
//5 = f
//These two arrays are treated the same because they're composed of strings.
var nums = ["10", "5", "40", "25", "100", "1"];
var chars = ["ba", "f", "ea", "cf", "baa", "b"];
//Here we can see that sort() correctly sorted these strings. Looking at the
//alphabetical characters we see that they are in the correct order. Looking
//at our numbers in the same light, it makes sense that they are sorted
//this way as well. After all, we did pass them as strings to our array.
chars.sort(); //["b", "ba", "baa", "cf", "ea", "f"]
nums.sort(); //["1", "10", "100", "25", "40", "5"]
//The bad part of sort() comes in when our array is actually made up of numbers.
var nums = [10, 5, 40, 25, 100, 1];
nums.sort(); //[1, 10, 100, 25, 40, 5]
//As a result of the default sorting function converting numbers to strings
//before sorting, we get an unwanted result. We can fix this by passing in our
//own function as a parameter to sort().
Вы можете управлять сортировкой массива путем передачи вашей собственной функции в качестве параметра функции sort()
. Это хорошо, но если вы не знаете, как работает функция sort()
, это действительно не принесет вам пользы.
sort()
будет вызывать вашу функцию несколько раз, чтобы перенастроить массив. В зависимости от того, что возвращается из вашей функции, сообщите sort()
, что делать с элементами в массиве. Если возвращается отрицательное число или 0, повторная организация не происходит. Если возвращается положительное число, переключаются два элемента. sort()
отслеживает, какие номера он уже тестировал, поэтому он не заканчивает тестирование номеров снова после того, как он переключил элементы вокруг. Если sort()
переустанавливает элементы, он будет перемещаться назад на одну позицию и видеть, проверял ли он эти два элемента раньше. Если он не проверит их. Если он есть, он будет продолжаться без выполнения вашей функции на них.
Сортировка номеров
Возьмем простой пример, и я пройду через него:
var arr = [50, 90, 1, 10, 2];
arr = arr.sort(function(current, next){
//My comments get generated from here
return current - next;
});
//1 : current = 50, next = 90
// : current - next (50 - 90 = -40)
// : Negative number means no re-arranging
// : Array now looks like [50, 90, 1, 10, 2]
//
//2 : current = 90, next = 1
// : current - next (90 - 1 = 89)
// : Positive number means sort() will switch these positions in the array
// : Array now looks like [50, 1, 90, 10, 2]
//
//If sort() didn't backtrack, the next check would be 90 and 10, switch those
//positions, check 90 and 2, and switch again. Making the final array
//[50, 1, 10, 2, 90], not sorted. But lucky for us, sort() does backtrack.
//
//3 : current = 50, next = 1
// : current - next (50 - 1 = 49)
// : Positive number means sort() will switch these positions in the array
// : Array now looks like [1, 50, 90, 10, 2]
//
//If sort() wasn't smart, it would now check 50 and 90 again. What a waste!
//But lucky for us again, sort() is smart and knows it already made this
//check and will continue on.
//
//4 : current = 90, next = 10
// : current - next (90 - 10 = 80)
// : Positive number means sort() will switch these positions in the array
// : Array now looks like [1, 50, 10, 90, 2]
//
//sort() backtracks one position and sees that it has not checked 50 and 10
//
//5 : current = 50, next = 10
// : current - next (50 - 10 = 40)
// : Positive number means sort() will switch these positions in the array
// : Array now looks like [1, 10, 50, 90, 2]
//
//sort() backtracks one position and sees that it has not checked 1 and 10
//
//6 : current = 1, next = 10
// : current - next (1 - 10 = -9)
// : Negative number means no re-arranging
// : Array now looks like [1, 10, 50, 90, 2]
//
//sort() remembers that it already checked 10 and 50 so it skips ahead
//sort() remembers that it already checked 50 and 90 so it skips ahead
//
//7 : current = 90, next = 2
// : current - next (90 - 2 = 88)
// : Positive number means sort() will switch these positions in the array
// : Array now looks like [1, 10, 50, 2, 90]
//
//sort() backtracks one position and sees that it has not checked 50 and 2
//
//8 : current = 50, next = 2
// : current - next (50 - 2 = 48)
// : Positive number means sort() will switch these positions in the array
// : Array now looks like [1, 10, 2, 50, 90]
//
//sort() backtracks one position and sees that it has not checked 10 and 2
//
//9 : current = 10, next = 2
// : current - next (10 - 2 = 8)
// : Positive number means sort() will switch these positions in the array
// : Array now looks like [1, 2, 10, 50, 90]
//
//sort() backtracks one position and sees that it has not checked 1 and 2
//
//10: current = 1, next = 2
// : current - next (1 - 2 = -1)
// : Negative number means no re-arranging
// : Array now looks like [1, 2, 10, 50, 90]
//
//sort() remembers that it already checked 2 and 10 so it skips ahead
//sort() remembers that it already checked 10 and 50 so it skips ahead
//sort() remembers that it already checked 50 and 90 so it skips ahead
//sort() has no more items to check so it returns the final array
//which is [1, 2, 10, 50, 90]
Если вы хотите, чтобы массив упорядочивался в порядке убывания [90, 50, 10, 2, 1]
, вы можете просто изменить оператор return от return current - next;
до return next - current;
следующим образом:
var arr = [50, 90, 1, 10, 2];
arr = arr.sort(function(current, next){
//My comments get generated from here
return next - current;
});
//1 : current = 50, next = 90
// : next - current (90 - 50 = 40)
// : Positive number means sort() will switch these positions in the array
// : Array now looks like [90, 50, 1, 10, 2]
//
//2 : current = 50, next = 1
// : next - current (1 - 50 = -49)
// : Negative number means no re-arranging
// : Array now looks like [90, 50, 1, 10, 2]
//
//etc.
Не имеет значения, если ваш массив состоит из "строковых чисел" "5"
или просто чисел 5
при использовании вашей собственной функции для сортировки чисел. Потому что, когда JavaScript выполняет математику, он обрабатывает "строковые числа" как числа. т.е. "5" - "3" = 2
Сортировка строк
При сортировке строк вы можете сравнить их с помощью операторов >
и <
(больше и меньше). Оператор большего размера сортирует строку по возрастанию (A-Z, 1-9), а оператор меньшего порядка сортирует по убыванию (Z-A, 9-1). В разных браузерах используются разные алгоритмы сортировки, поэтому при сортировке по строкам вы должны убедиться, что вы возвращаете 1 или -1, а не true или false.
Например, это работает в Chrome и FF, но не в IE:
var arr = ['banana', 'orange', 'apple', 'grape'];
arr = arr.sort(function(current, next){
return current > next;
});
Чтобы убедиться, что ваш алгоритм сортировки работает в каждом браузере, используйте тернарный оператор.
var arr = ['banana', 'orange', 'apple', 'grape'];
arr = arr.sort(function(current, next){
return current > next? 1: -1;
});
При изменении способа сортировки (по возрастанию или убыванию), помимо изменения операторов, вы можете сохранить один и тот же оператор и переключить переменные current
и next
, как это было при сортировке чисел. Или, поскольку мы используем тернарный оператор, вы можете переключить 1
и -1
.
Сортировка объектов
Вот аккуратный трюк, который, как я думал, я бы добавил сюда. Вы можете сортировать объекты, если их добавить в массив, и использовать их ключ для сравнения. Вот пример.
var arr = [
{id: 2, name: 'Paul'},
{id: 1, name: 'Pete'}
];
//sort numerically
arr = arr.sort(function(current, next){
return current.id - next.id;
});
//Array now looks like [{id: 1, name: 'Pete'}, {id: 2, name: 'Paul'}]
//sort alphabetically
arr = arr.sort(function(current, next){
return current.name > next.name? 1: -1;
});
//Array now looks like [{id: 2, name: 'Paul'}, {id: 1, name: 'Pete'}]
Резюме
Сортировка номеров
в порядке возрастания (1, 2, 3...): function(a, b){return a - b;}
в порядке убывания (9, 8, 7...): function(a, b){return b - a;}
Сортировка строк
в порядке возрастания (A, B, C...): function(a, b){return a > b? 1: -1;}
в порядке убывания (Z, Y, X...): function(a, b){return b > a? 1: -1;}
Чтобы отсортировать объекты, добавьте их в массив,
затем отсортируйте по ключу: function(a, b){return a.key - b.key;}