在 JavaScript 中对数组进行排序:实际示例

JavaScript 是一种多功能语言,它为开发人员提供了一系列内置方法来操作数据,包括对数组进行排序。在这篇文章中,我们探索了Array.prototype.sort()方法的复杂性,展示了它在各种场景中的用法,并探讨了它的局限性和注意事项。到本文结束时,您将深入了解 JavaScript 中的数组排序,包括处理单个和多个排序条件、区分大小写和不区分大小写的排序,以及管理就地排序的结果。
基本用法
该Array.prototype.sort()方法是 JavaScript 提供的内置函数,可以方便地对数组元素进行排序。默认情况下,该sort()方法按升序对数组元素进行排序,将它们视为字符串并比较它们的 UTF-16 代码单元值序列。要使用该sort()方法,只需在要排序的数组上调用它即可。例如:

javascript
复制
const fruits = [‘banana’, ‘apple’, ‘mango’, ‘kiwi’];
fruits.sort();
console.log(fruits); // Output: [“apple”, “banana”, “kiwi”, “mango”]
虽然该方法的默认行为sort()对于简单的情况可能已经足够,但它通常需要自定义来处理特定的排序要求。在以下部分中,我们将讨论如何sort()使用比较函数自定义方法,并探索各种排序场景以更好地了解其用法和功能。

比较函数的作用
比较函数在自定义sort()JavaScript 方法的排序行为方面起着至关重要的作用。通过提供自定义比较函数作为sort()方法的参数,我们可以为其特定用例定义确切的排序标准。比较函数应接受两个参数,通常称为aand b,并根据所需顺序返回负值、正值或零值。如果返回值小于 0,a应该放在前面b;如果大于 0,a应该在 之后b;如果等于 0,则a和的顺序b没关系。这种灵活的方法允许精确控制排序过程,支持对数字、字符串、对象或任何自定义数据类型进行排序,以及处理升序或降序。

数字排序
默认情况下,该Array.prototype.sort()方法将元素视为字符串,这可能会在对数字进行排序时导致意外结果。例如,对整数数组进行排序[10, 5, 100, 30]会产生[10, 100, 30, 5],这不是预期的结果。

发生这种情况是因为元素被视为字符串并根据它们的 UTF-16 代码单元值按字典顺​​序进行比较(要获取字符串的 UTF-16 代码,您可以使用 String.prototype.charCodeAt() 方法)。在这种情况下,“30”出现在“5”之前,因为第一个字符“3”在转换为 UTF-16 时小于“5”。为了正确排序数字,我们需要提供自定义比较函数。在对字符串值进行排序时,此函数不需要返回0、-1或1like ,而是可以b从 中减去a。

javascript
复制
const numbers = [10, 5, 100, 30];
numbers.sort((a, b) => a - b);
console.log(numbers); // Output: [5, 10, 30, 100]
在此示例中,比较函数(a, b) => a - b计算两个数值之间的差异,确保它们按升序排序。如果要按降序对数字进行排序,只需反转操作即可:(a, b) => b - a。这种直接的数字排序方法也可以扩展到处理浮点数。

按字母排序
当我们对fruits数组进行排序时,默认的字典排序就足够了,因为所有字符串都是ASCII字符并且具有相同的大小写。考虑一个不同的数组:

javascript
复制
const fruits = [“banana”, “apple”, “Mango”, “kiwi”];
fruits.sort();
console.log(fruits); // Output: [‘Mango’, ‘apple’, ‘banana’, ‘kiwi’]
在这种情况下,顺序不正确,因为在 UTF-16 尺度上大写字母“M”出现在所有小写字符之前。此外,如果数组中有任何非英语的字符串,排序结果也会不正确。

为了解决这个问题,我们可以使用String.prototype.localeCompare方法,它返回一个数字,指示引用字符串是在排序顺序之前、之后还是与给定字符串相同。此外,它还接受第三个选项参数,该参数具有一个sensitivity属性。将其设置为base将使用不区分大小写的排序。

javascript
复制
const fruits = [“banana”, “apple”, “Mango”, “kiwi”];
fruits.sort((a, b) => a.localeCompare(b, undefined, { sensitivity: “base” }));
console.log(fruits); // Output: [‘apple’, ‘banana’, ‘kiwi’, ‘Mango’]
将敏感度选项设置为base将执行不区分大小写的排序,但它也会忽略字符之间的重音差异。如果要在考虑重音差异的同时执行不区分大小写的排序,则应将敏感度选项设置为accent。

在某些现代浏览器(如 Chrome)中,localeCompare()默认情况下,该方法会根据浏览器的区域设置执行不区分大小写的排序,即使不指定选项也可能会产生预期的结果sensitivity。但是,并不能保证在所有环境和浏览器版本中都有这种行为,因为其他浏览器或旧版本的默认行为可能不同。

Map如果您对在 JavaScript 中使用数据结构感到好奇,您可能会发现这些帖子很有帮助:使用 JavaScript 中的地图删除重复项和使用 JavaScript 和 React 中的地图简化代码。

按对象属性对对象数组进行排序
根据特定属性值对对象数组进行排序是 JavaScript 开发中的常见需求。为此,可以为该Array.prototype.sort()方法提供自定义比较功能。该函数比较两个对象的属性值并相应地对它们进行排序。

让我们考虑一个示例,其中我们有一个对象数组,这些对象代表具有 name 和 age 属性的人:

javascript
复制
const people = [
{ name: ‘Alice’, age: 30 },
{ name: ‘Bob’, age: 25 },
{ name: ‘Charlie’, age: 35 }
];
people.sort((a, b) => a.age - b.age);
console.log(people);
/* Output: [
{ name: “Bob”, age: 25 },
{ name: “Alice”, age: 30 },
{ name: “Charlie”, age: 35 },
]; */
在此示例中,比较函数(a, b) => a.age - b.age根据对象的age属性按升序对对象进行排序。

按多个属性对对象数组进行排序
当您需要根据多个属性对对象数组进行排序时,您可以扩展自定义比较函数以在第一个属性值相等时比较其他属性。为此,您可以使用逻辑 OR 运算符按优先级顺序为每个属性定义排序标准:

javascript
复制
const people = [
{ name: ‘Alice’, age: 30 },
{ name: ‘Bob’, age: 30 },
{ name: ‘Charlie’, age: 35 },
{ name: ‘David’, age: 30 }
];
people.sort((a, b) => a.age - b.age || a.name.localeCompare(b.name));
console.log(people);
/* Output: [
{ name: “Alice”, age: 30 },
{ name: “Bob”, age: 30 },
{ name: “David”, age: 30 },
{ name: “Charlie”, age: 35 },
]; */
在此示例中,比较函数首先比较age属性值。如果它们相等,则比较name属性值localeCompare()以确保字典排序。对象根据它们的age属性升序排序,如果它们的年龄相等,则它们根据它们的name属性升序排序。

按特定顺序按对象属性对对象数组进行排序
在某些情况下,您可能需要按特定顺序对对象数组进行排序。例如,您可能希望以特定方式按地址对人员进行排序。为此,我们定义了一个addressOrder指定地址顺序的数组,并创建了一个compareObjects函数来获取数组中比较属性的索引addressOrder。

js
复制
const data = [
{ name: “John”, age: 30, address: “123 Main St” },
{ name: “Jane”, age: 25, address: “456 Elm St” },
{ name: “Bob”, age: 40, address: “789 Oak St” },
];

const addressOrder = [“456 Elm St”, “123 Main St”, “789 Oak St”];

const compareObjects = (a, b) => {
const aIndex = addressOrder.indexOf(a.address);
const bIndex = addressOrder.indexOf(b.address);
return aIndex - bIndex;
};

data.sort(compareObjects);
console.log(data);
/* Output: [
{ name: “Jane”, age: 25, address: “456 Elm St” },
{ name: “John”, age: 30, address: “123 Main St” },
{ name: “Bob”, age: 40, address: “789 Oak St” },
]; */
由于索引是数值,我们可以使用简化的比较函数进行数值比较。

请注意,此实现假定data数组中的所有地址属性都包含在addressOrder数组中。如果data数组包含具有数组中不存在的属性的对象addressOrder,compareObjects则需要修改函数以解决该问题。

javascript
复制
const data = [
{ name: ‘John’, age: 30, address: ‘123 Main St’ },
{ name: ‘Jane’, age: 25, address: ‘456 Elm St’ },
{ name: ‘Bob’, age: 40, address: ‘789 Oak St’ },
{ name: ‘Alice’, age: 35, address: ‘1001 Maple St’ },
];

const addressOrder = [‘456 Elm St’, ‘123 Main St’, ‘789 Oak St’];

const compareObjects = (a, b) => {
const aIndex = addressOrder.indexOf(a.address);
const bIndex = addressOrder.indexOf(b.address);

if (aIndex === -1 && bIndex !== -1) {
return 1;
} else if (aIndex !== -1 && bIndex === -1) {
return -1;
} else if (aIndex === -1 && bIndex === -1) {
return a.address.localeCompare(b.address);
} else {
return aIndex - bIndex;
}
};

data.sort(compareObjects);
console.log(data);
/* Output: [
{ name: “Jane”, age: 25, address: “456 Elm St” },
{ name: “John”, age: 30, address: “123 Main St” },
{ name: “Bob”, age: 40, address: “789 Oak St” },
{ name: ‘Alice’, age: 35, address: ‘1001 Maple St’ },
]; */
在此示例中,我们有一个地址为“1001 Maple St”的“Alice”对象,该对象不存在于数组中addressOrder。该compareObjects函数现在检查索引值是否为-1。如果两个对象的地址都没有在addressOrder数组中找到,它会使用字典顺序对它们进行排序localeCompare()。如果只有一个地址未找到,则将该对象放在已排序数组的末尾。

Array.prototype.sort() 的限制和警告
虽然该Array.prototype.sort()方法是在 JavaScript 中对数组进行排序的一种通用且方便的方法,但它具有一些开发人员需要注意的限制和注意事项。

首先,如前所述,默认的排序行为是字典顺序的,这可能会为数字或混合类型数组产生意想不到的结果。为了获得所需的排序顺序,通常需要自定义比较功能。

其次,该sort()方法不能保证稳定,这意味着具有相同排序键的元素可能不会保留其原始顺序。尽管一些 JavaScript 引擎,如 V8,已经实现了稳定的排序,但这种行为在所有环境中并不一致。

第三,该方法的性能sort()因 JavaScript 引擎和使用的排序算法而异。在某些情况下,内置排序方法可能不是大型数据集或特定排序要求的最有效解决方案。

最后,该sort()方法执行就地排序,这意味着它修改原始数组而不是创建新的排序数组。虽然这种方法内存效率高并且通常是可取的,但它也有开发人员应注意的潜在后果。一个结果是元素的原始顺序丢失,因为原始数组在排序过程中被直接修改。在需要保留原始顺序的情况下,建议在排序之前创建数组的副本。另一个结果是,当存在对同一数组的多个引用时,就地排序可能会无意中影响应用程序的其他部分。

应该注意的是,sort()存在该方法的不可变版本 - Array.prototype.toSorted(),尽管它在某些主要浏览器中的支持是有限的。但是,它已进入TC39 流程的第 4 阶段,预计将包含在即将发布的 ECMAScript 版本 - ECMAScript 2023 中。

结论
掌握在 JavaScript 中对数组进行排序的艺术对于任何开发人员来说都是一项宝贵的技能。在本指南中,我们探讨了该方法的来龙去脉Array.prototype.sort(),包括其基本用法、自定义比较函数以及解决限制和注意事项。通过理解和应用这些概念,您可以在 JavaScript 中有效地对数组进行排序,定制排序逻辑以满足您的应用程序的需要。随着您不断提高您的 JavaScript 技能,请记住考虑您的排序选择的影响并探索替代技术和库以获得最有效和准确的排序结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Q shen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值