按字符串属性值对对象数组进行排序
技术背景
在 JavaScript 开发中,经常会遇到需要对对象数组按照某个字符串属性值进行排序的需求。例如,对用户列表按照姓氏排序,对商品列表按照名称排序等。JavaScript 提供了 Array.prototype.sort()
方法来实现排序,同时也有许多不同的方式可以实现按字符串属性值排序。
实现步骤
自定义比较函数
可以编写自定义的比较函数来实现排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function compare(a, b) { if (a.last_nom < b.last_nom) { return -1; } if (a.last_nom > b.last_nom) { return 1; } return 0; }
const objs = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ];
objs.sort(compare); console.log(objs);
|
内联比较函数
可以使用内联的箭头函数来简化代码。
1 2 3 4 5 6 7 8
| const objs = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ];
objs.sort((a, b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0)); console.log(objs);
|
动态排序函数
可以创建一个动态排序函数,根据传入的属性名进行排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| function dynamicSort(property) { let sortOrder = 1; if (property[0] === "-") { sortOrder = -1; property = property.substr(1); } return function (a, b) { const result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0; return result * sortOrder; }; }
const People = [ { Name: "Name", Surname: "Surname" }, { Name: "AAA", Surname: "ZZZ" }, { Name: "Name", Surname: "AAA" } ];
People.sort(dynamicSort("Name")); People.sort(dynamicSort("Surname")); People.sort(dynamicSort("-Surname")); console.log(People);
|
多参数排序函数
可以创建一个多参数排序函数,根据多个属性进行排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function dynamicSortMultiple() { const props = arguments; return function (obj1, obj2) { let i = 0, result = 0, numberOfProperties = props.length; while (result === 0 && i < numberOfProperties) { result = dynamicSort(props[i])(obj1, obj2); i++; } return result; }; }
const People = [ { Name: "Name", Surname: "Surname" }, { Name: "AAA", Surname: "ZZZ" }, { Name: "Name", Surname: "AAA" } ];
People.sort(dynamicSortMultiple("Name", "-Surname")); console.log(People);
|
使用 ES6 的 localeCompare
方法
在 ES6 及以后的版本中,可以使用 localeCompare
方法进行排序。
1 2 3 4 5 6 7 8
| const objs = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ];
objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom)); console.log(objs);
|
使用 Underscore.js 或 Lodash
可以使用 Underscore.js 或 Lodash 库来实现排序。
1 2 3 4 5 6 7 8 9
| const _ = require('lodash'); const objs = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ];
const sortedObjs = _.sortBy(objs, 'last_nom'); console.log(sortedObjs);
|
使用 Intl.Collator
进行自然排序
当需要进行自然字符串排序时,可以使用 Intl.Collator
。
1 2 3 4 5 6 7 8 9 10 11 12 13
| const files = [ { name: "1.mp3", size: 123 }, { name: "10.mp3", size: 456 }, { name: "100.mp3", size: 789 }, { name: "11.mp3", size: 123 }, { name: "111.mp3", size: 456 }, { name: "2.mp3", size: 789 } ];
const naturalCollator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });
files.sort((a, b) => naturalCollator.compare(a.name, b.name)); console.log(files);
|
核心代码
以下是一些核心代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| function compare(a, b) { if (a.last_nom < b.last_nom) { return -1; } if (a.last_nom > b.last_nom) { return 1; } return 0; }
function dynamicSort(property) { let sortOrder = 1; if (property[0] === "-") { sortOrder = -1; property = property.substr(1); } return function (a, b) { const result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0; return result * sortOrder; }; }
function dynamicSortMultiple() { const props = arguments; return function (obj1, obj2) { let i = 0, result = 0, numberOfProperties = props.length; while (result === 0 && i < numberOfProperties) { result = dynamicSort(props[i])(obj1, obj2); i++; } return result; }; }
const objs = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ];
objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));
|
最佳实践
- 当排序逻辑简单时,使用内联箭头函数可以简化代码。
- 当需要根据不同属性动态排序时,使用动态排序函数。
- 当需要根据多个属性排序时,使用多参数排序函数。
- 在 ES6 及以后的版本中,优先使用
localeCompare
方法进行字符串排序。 - 如果项目中已经使用了 Underscore.js 或 Lodash 库,可以使用它们提供的排序方法。
常见问题
大小写敏感问题
默认的比较函数是大小写敏感的。如果需要忽略大小写,可以在比较时将字符串转换为小写或大写。
1 2 3 4 5 6 7 8
| const arr = [ { name: 'Apple' }, { name: 'banana' }, { name: 'Cherry' } ];
arr.sort((a, b) => a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1); console.log(arr);
|
排序稳定性问题
JavaScript 的 Array.prototype.sort()
方法在不同浏览器中的排序稳定性可能不同。如果需要稳定排序,可以使用第三方库或自定义排序算法。