JavaScript中的sort函数可以用来对数组进行排序,默认情况下sort函数会将数组中的元素转换为字符串,并按照Unicode码点的顺序进行排序(Unicode码点是由前缀“U+”和一个十六进制数字组成,它具有全球统一、扩展性强、多语言支持等特点)
接下来讲一下 sort函数常见的用法:
定义和用法
sort() 方法用于对数组的元素进行排序。
排序顺序可以是字母或数字,并按升序或降序。
默认排序顺序为按字母升序。
**注意:**当数字是按字母顺序排列时"20"将排在"1"前面。
使用数字排序,你必须通过一个函数作为参数来调用。
函数指定数字是按照升序还是降序排列。
这个时候大家一定会很疑惑 为什么"20"将排在"1"前面呢,接下来听我细细道来
1. 字符串比较规则
-
在字符串比较中,"20"和"1"的比较是基于他们的字符顺序。
-
由于"2"在ASCII码表中的值大于"1",因此当比较"20"和"1"的第一个字符时,"20"就被认为大于"1"。
2. 数字转换为字符串后的比较
-
当数字“20”和“1”被转换为字符串后,它们分别变为“20”和“1”。
-
按照字符串比较的规则,“20”的第一个字符“2”大于“1”的第一个字符“1”,因此“20”会被排在“1”前面。
所以使用数字排序的时候 我们需要通过一个函数作为参数来进行调用,接下来给大家举个例子
const arr = [1, 30, 4, 21, 100000, 20];
arr.sort((a, b) => a - b); // 升序排序
console.log(arr); // 输出: [1, 4, 20, 21, 30, 100000]
在这个例子中,我们提供了一个箭头函数作为比较函数,它返回两个数字的差(a - b)。这样,sort()方法就会根据这个差值来决定元素的顺序,从而实现正确的数字排序。
那么a-b和b-a有什么区别呢
1. a-b(升序排列)
-
当 a < b 时,a - b 为负值,所以 a 会排在 b 前面。
-
当 a > b 时,a - b 为正值,所以 a 会排在 b 后面。
-
这符合从小到大的升序排序规则。
const arr = [5, 2, 9, 1, 5, 6]; arr.sort((a, b) => a - b); console.log(arr); // [1, 2, 5, 5, 6, 9]
2. b-a(降序排列)
-
当 a < b 时,b - a 为正值,所以 a 会排在 b 后面。
-
当 a > b 时,b - a 为负值,所以 a 会排在 b 前面。
-
这符合从大到小的降序排序规则。
const arr = [5, 2, 9, 1, 5, 6]; arr.sort((a, b) => b - a); console.log(arr); // [9, 6, 5, 5, 2, 1]
总结来说:
-
使用 a - b 会导致数组按升序排序。
-
使用 b - a 会导致数组按降序排序。
如果我们想对对象数组进行排序改怎么做呢
假设你有一个对象数组,每个对象都有一个 age 属性,你想根据 age 属性对数组进行排序。你可以这样做:
const people = [{ name: 'Alice', age: 30 },{ name: 'Bob', age: 25 },{ name: 'Charlie', age: 35 }];// 使用 sort 方法并传入比较函数
people.sort((a, b) => a.age - b.age);
console.log(people);
在这个例子中,比较函数 (a, b) => a.age - b.age 定义了排序规则:
-
如果 a.age - b.age 小于 0,那么 a 会被排在 b 前面。
-
如果 a.age - b.age 大于 0,那么 a 会被排在 b 后面。
-
如果 a.age - b.age 等于 0,那么 a 和 b 的相对位置不变(但具体顺序可能会因浏览器实现而异)。
如果你想根据其他属性进行排序,比如 name 属性,你可以使用字符串的 localeCompare 方法,它会自动处理字符串的比较:
// 使用 localeCompare 方法根据 name 属性进行排序
people.sort((a, b) => a.name.localeCompare(b.name));
console.log(people);
localeCompare 方法会考虑字符串的本地化排序规则,对于大多数情况来说是一个更健壮的选择。
总结:
-
使用 sort 方法对对象数组进行排序时,需要提供一个比较函数。
-
比较函数定义了排序规则,通常根据对象的某个属性进行比较。
-
可以使用简单的算术运算或字符串的 localeCompare 方法来实现比较逻辑。
sort相比较于冒泡排序的优点在哪呢
性能比较
1.时间复杂度:
-
冒泡排序:平均和最坏情况下的时间复杂度为O(n2),其中 n 是数组的长度。
-
Array.prototype.sort():在现代JavaScript引擎中,sort() 方法通常基于快速排序(Quick Sort)或 Timsort(一种混合排序算法,结合了归并排序和插入排序的特点,适用于多种实际数据模式)。其平均时间复杂度为O(nlogn),这在大多数情况下优于O(n2)。
2.实现优化:
-
内置排序:JavaScript引擎对 sort() 方法进行了高度优化,利用了底层硬件和并行处理的优势。
-
手动实现:除非有特别的优化(例如,针对特定数据模式的优化),否则手动实现的冒泡排序很难达到相同级别的性能。
3.浏览器差异:
- 不同浏览器和JavaScript引擎对 sort() 方法的实现和优化程度可能有所不同,但通常都优于大多数手动实现的排序算法。
为什么要使用 sort() 而不是手写冒泡排序?
-
性能:如上所述,
sort()方法通常比冒泡排序更快,特别是在处理大量数据时。 -
可读性和维护性:使用内置方法可以使代码更简洁、易读,并且减少了出错的可能性。冒泡排序的代码虽然简单,但在实际应用中可能不易理解和维护。
-
可靠性:内置方法经过广泛测试和验证,更可靠,减少了因实现错误导致的潜在问题。
-
扩展性和灵活性:
sort()方法可以接受一个可选的比较函数,允许对数组进行自定义排序。相比之下,冒泡排序的灵活性较差,实现自定义排序逻辑相对复杂。
示例
以下是一个使用 sort() 方法对数组进行排序的示例:
const numbers = [5, 2, 9, 1, 5, 6];
numbers.sort((a, b) => a - b);
console.log(numbers); // 输出: [1, 2, 5, 5, 6, 9]
而使用冒泡排序实现相同功能的代码可能如下:
function bubbleSort(arr) {
let n = arr.length;
for (let i = 0; i < n - 1; i++) {
for (let j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
// 交换元素
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;}
const numbers = [5, 2, 9, 1, 5, 6];
console.log(bubbleSort(numbers)); // 输出: [1, 2, 5, 5, 6, 9]
结论
在大多数情况下,使用 Array.prototype.sort() 方法进行排序是更好的选择,因为它提供了更高的性能、更好的可读性和维护性,以及更大的灵活性和可靠性。除非有特定的性能需求或需要实现自定义排序逻辑,否则通常不建议手动实现排序算法。(有现成的为什么要自己手写呢 狗头.jpg)
感兴趣的话可以关注我的公众号:小刘的进步日常