数组排序的自定义比较函数

在JavaScript中,数组排序是一个常见且强大的操作。虽然JavaScript提供了默认的排序方法sort(),但很多时候我们需要根据特定需求对数组进行自定义排序。这时,自定义比较函数就派上用场了。

基本排序方法

JavaScript的Array.prototype.sort()方法默认将元素转换为字符串,然后按照UTF-16代码单元值序列进行排序:

javascript 复制代码
const fruits = ['banana', 'apple', 'cherry'];
fruits.sort();
console.log(fruits); // ['apple', 'banana', 'cherry']

对于数字排序,默认行为可能不符合预期:

javascript 复制代码
const numbers = [10, 5, 40, 25];
numbers.sort();
console.log(numbers); // [10, 25, 40, 5] - 不是我们想要的数字顺序

自定义比较函数

为了正确排序数字或其他复杂数据类型,我们需要提供自定义比较函数。比较函数接收两个参数(通常称为a和b),并根据以下规则返回值:

  • 如果a应该排在b前面,返回负数(通常-1)
  • 如果a应该排在b后面,返回正数(通常1)
  • 如果a和b相等,返回0

数字排序

javascript 复制代码
const numbers = [10, 5, 40, 25];
numbers.sort((a, b) => a - b);
console.log(numbers); // [5, 10, 25, 40] - 升序

numbers.sort((a, b) => b - a);
console.log(numbers); // [40, 25, 10, 5] - 降序

对象数组排序

当排序对象数组时,比较函数可以基于对象属性:

javascript 复制代码
const users = [
  { name: 'John', age: 25 },
  { name: 'Jane', age: 20 },
  { name: 'Bob', age: 30 }
];

// 按年龄升序
users.sort((a, b) => a.age - b.age);

// 按名字字母顺序
users.sort((a, b) => a.name.localeCompare(b.name));

多条件排序

有时我们需要基于多个属性进行排序:

javascript 复制代码
const products = [
  { name: 'Laptop', price: 1000, stock: 5 },
  { name: 'Phone', price: 500, stock: 10 },
  { name: 'Tablet', price: 500, stock: 3 }
];

// 先按价格升序,价格相同则按库存降序
products.sort((a, b) => {
  if (a.price !== b.price) {
    return a.price - b.price;
  }
  return b.stock - a.stock;
});

注意事项

  1. 原地排序sort()方法会修改原数组,如果需要保留原数组,可以先创建副本:

    javascript 复制代码
    const sorted = [...array].sort(compareFunction);
  2. 稳定性:从ES2019开始,JavaScript要求排序算法是稳定的(相同元素保持原始顺序)

  3. 性能:对于大型数组,自定义比较函数的性能可能成为瓶颈,需要考虑优化

高级用法

按字符串长度排序

javascript 复制代码
const words = ['apple', 'banana', 'cherry', 'date'];
words.sort((a, b) => a.length - b.length);

按自定义顺序排序

javascript 复制代码
const priority = ['high', 'medium', 'low'];
const tasks = [
  { title: 'Task 1', priority: 'medium' },
  { title: 'Task 2', priority: 'high' },
  { title: 'Task 3', priority: 'low' }
];

tasks.sort((a, b) => priority.indexOf(a.priority) - priority.indexOf(b.priority));

自然排序(数字在字符串中)

javascript 复制代码
const files = ['file1', 'file10', 'file2', 'file20'];
files.sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
// ['file1', 'file2', 'file10', 'file20']

掌握自定义比较函数的使用,可以让你在JavaScript中灵活处理各种复杂的排序需求,大大提升数组操作的效率和精确度。