JavaScript中sort的常见用法

528 阅读6分钟

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() 而不是手写冒泡排序?

  1. 性能:如上所述,sort() 方法通常比冒泡排序更快,特别是在处理大量数据时。

  2. 可读性和维护性:使用内置方法可以使代码更简洁、易读,并且减少了出错的可能性。冒泡排序的代码虽然简单,但在实际应用中可能不易理解和维护。

  3. 可靠性:内置方法经过广泛测试和验证,更可靠,减少了因实现错误导致的潜在问题。

  4. 扩展性和灵活性: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)

感兴趣的话可以关注我的公众号:小刘的进步日常