如何在JavaScript中对对象数组进行排序

开发 前端
如果需要按特定顺序对对象数组进行排序,我们很有可能会直接找个 JS 库来用。其实大可不必,JS 原生中的 Array.sort就能直接一些复杂又漂亮的排序。

 [[354152]]

如果需要按特定顺序对对象数组进行排序,我们很有可能会直接找个 JS 库来用。其实大可不必,JS 原生中的 Array.sort就能直接一些复杂又漂亮的排序。

本文中,将介绍一些 Array.sort 的常规排序和一些骚操作。

基本数组排序

默认情况下,Array.sort函数将数组中需要排序的每个元素转换为字符串,并按 Unicode 顺序对其进行比较。

  1. const foo = [9, 1, 4, 'zebroid''afterdeck']; 
  2. foo.sort(); // returns [ 1, 4, 9, 'afterdeck''zebroid' ] 
  3.  
  4. const bar = [5, 18, 32, new Set, { user'Eleanor Roosevelt' }]; 
  5. bar.sort(); // returns [ 18, 32, 5, { user'Eleanor Roosevelt' }, Set {} ] 

你可能会好奇为啥32排在5之前。发生这种情况是因为数组中的每个元素都首先转换为字符串,并且按照Unicode顺序,"32"在"5"之前。

需要注意的是,Array.sort会更改原数组。

  1. const baz = ['My cat ate my homework', 37, 9, 5, 17]; 
  2. baz.sort(); // baz数组被修改 
  3. console.log(baz); // shows [ 17, 37, 5, 9, 'My cat ate my homework' ] 

为避免这种情况,我们可以创建要排序的数组的新实例,然后在新的数组上进行修改。这里可以使用 Array.slice它返回是一个新的数组实例。

  1. // 创建baz数组的新实例并对其进行排序 
  2. const sortedBaz = baz.slice().sort(); 

我们还可以使用 ES6 中的展开运算符来做:

  1. const sortedBaz = [...baz].sort();  

在两种情况下,输出是相同的:

  1. console.log(baz); // ['My cat ate my homework', 37, 9, 5, 17]; 
  2. console.log(sortedBaz); // [ 17, 37, 5, 9, 'My cat ate my homework' ] 

单独使用Array.sort不能对对象数组进行排序。但不必担心,sort 的还提供一个参数,该参数使数组元素根据compare函数的返回值进行排序。

使用比较函数进行排序

假设foo和bar是compare函数要比较的两个元素,compare函数的返回值设置如下:

  1. 小于0:foo在bar之前
  2. 大于0 :bar在foo之前
  3. 等于0:foo和bar彼此保持不变。

来看一个简单的示例:

  1. const nums = [79, 48, 12, 4]; 
  2.  
  3. function compare(a, b) { 
  4.   if (a > b) return 1; 
  5.   if (b > a) return -1; 
  6.  
  7.   return 0; 
  8.  
  9. nums.sort(compare); 
  10. // => 4, 12, 48, 79 

我们可以稍微重构一下:

  1. function compare(a, b) { 
  2.   return a - b; 

使用在使用箭头函数进行重构:

  1. nums.sort((a, b) => a - b); 

如何对对象数组进行排序

现在,我们来按一下对对象数组的排序。假设有下面的 singers 数组:

  1. const singers = [ 
  2.   { name'Steven Tyler', band: 'Aerosmith', born: 1948 }, 
  3.   { name'Karen Carpenter', band: 'The Carpenters', born: 1950 }, 
  4.   { name'Kurt Cobain', band: 'Nirvana', born: 1967 }, 
  5.   { name'Stevie Nicks', band: 'Fleetwood Mac', born: 1948 }, 
  6. ]; 

我们可以使用 compare函数,然后根据 singers 中的 band 字段来进行排序。

  1. function compare(a, b) { 
  2.   // 使用 toUpperCase() 忽略字符大小写 
  3.   const bandA = a.band.toUpperCase(); 
  4.   const bandB = b.band.toUpperCase(); 
  5.  
  6.   let comparison = 0; 
  7.   if (bandA > bandB) { 
  8.     comparison = 1; 
  9.   } else if (bandA < bandB) { 
  10.     comparison = -1; 
  11.   } 
  12.   return comparison; 
  13.  
  14. singers.sort(compare); 
  15.  
  16. /* returns [ 
  17.   { name'Steven Tyler', band: 'Aerosmith',  born: 1948 }, 
  18.   { name'Stevie Nicks', band: 'Fleetwood Mac', born: 1948 }, 
  19.   { name'Kurt Cobain', band: 'Nirvana', born: 1967 }, 
  20.   { name'Karen Carpenter', band: 'The Carpenters', born: 1950 } 
  21. ] */ 

如果要让上面的顺序相反,可以这么做:

  1. function compare(a, b) { 
  2.   ... 
  3.  
  4.   // 乘以-1来反转返回值 
  5.   return comparison * -1; 

创建一个动态排序函数

最后,排序函数更具动态性。

我们创建一个排序函数,可以使用该函数对一组对象进行排序,这些对象的值可以是字符串或数字。该函数有两个参数-我们要排序的键和返回结果的顺序(即升序或降序):

  1. const singers = [ 
  2.   { name'Steven Tyler', band: 'Aerosmith', born: 1948 }, 
  3.   { name'Karen Carpenter', band: 'The Carpenters', born: 1950 }, 
  4.   { name'Kurt Cobain', band: 'Nirvana', born: 1967 }, 
  5.   { name'Stevie Nicks', band: 'Fleetwood Mac', born: 1948 }, 
  6. ]; 
  7.  
  8. function compareValues(keyorder = 'asc') { 
  9.   return function innerSort(a, b) { 
  10.     if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) { 
  11.       // 该属性在其中一个对象上不存在 
  12.       return 0; 
  13.     } 
  14.  
  15.     const varA = (typeof a[key] === 'string'
  16.       ? a[key].toUpperCase() : a[key]; 
  17.     const varB = (typeof b[key] === 'string'
  18.       ? b[key].toUpperCase() : b[key]; 
  19.  
  20.     let comparison = 0; 
  21.     if (varA > varB) { 
  22.       comparison = 1; 
  23.     } else if (varA < varB) { 
  24.       comparison = -1; 
  25.     } 
  26.     return ( 
  27.       (order === 'desc') ? (comparison * -1) : comparison 
  28.     ); 
  29.   }; 

使用:

  1. //数组按`band`排序,默认为升序 
  2. singers.sort(compareValues('band')); 
  3.  
  4. // 数组按 `band` 降序排序 
  5. singers.sort(compareValues('band''desc')); 
  6.  
  7. // 数组按 `name` 升序排序 
  8. singers.sort(compareValues('name')); 
  9.  
  10. // 数 组born 降序排序 
  11. singers.sort(compareValues('born''desc')); 

在上面的代码中,hasOwnProperty方法用于检查指定的属性是否在每个对象上定义,且没有通过原型链继承。如果没有在两个对象上定义,函数返回0,排序顺序保持不变(即对象之间保持不变)。

typeof运算符还用于检查属性值的数据类型,这使函数可以确定对数组进行排序的正确方法。如果指定属性的值是一个字符串,则使用toUpperCase方法将其所有字符都转换为大写,因此排序时将忽略字符大小写

最后,你可以根据自己需求来调整上面的函数。

String.prototype.localeCompare()

在上面的示例中,我们希望能够对对象数组进行排序,其值可以是字符串或数字。但是,如果我们知道处理值是字符串的对象,则可以使用 JS 的localeCompare方法

比较两个字符串,并返回下列值中的一个:

  • 如果 字符串 在 字母 表中 应该 排在 字符串 参数 之前, 则 返回 一个 负数;
  • 如果 字符串 等于 字符串 参数, 则 返回 0;
  • 字符串 在 字母 表中 应该 排在 字符串 参数 之后, 则 返回 一个 正数;
  1. ['bjork''Bjork''Björk'].sort(); 
  2. // [ 'Bjork''Björk''bjork' ] 
  3.  
  4. ['bjork''Bjork''Björk'].sort((a, b) => a.localeCompare(b)); 
  5. //  [ 'bjork''Bjork''Björk' ] 

根据compareValues函数,我们可以这么写:

  1. function compareValues(keyorder = 'asc') { 
  2.   return function innerSort(a, b) { 
  3.     if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) return 0; 
  4.     const comparison = a[key].localeCompare(b[key]); 
  5.  
  6.     return ( 
  7.       (order === 'desc') ? (comparison * -1) : comparison 
  8.     ); 
  9.   }; 

总结

上面就是使用普通JS 函数对对象数组排序的简短的介绍。尽管许多库都提供了这种动态排序能力,但我们自己实现这个方法其实也不信。另外,了解幕后发生了对我们来说并没有坏处。

今天就跟大家分享到这里了,感谢大家的观看,我们下期再见。

作者:James Hibbard 译者:前端小智 来源:sitepoint

原文:https://www.sitepoint.com/sort-an-array-of-objects-in-javascript/

本文转载自微信公众号「大迁世界」,可以通过以下二维码关注。转载本文请联系大迁世界公众号。

 

责任编辑:武晓燕 来源: 大迁世界
相关推荐

2021-03-18 10:45:02

JavaScript数组运算符

2021-03-11 23:43:20

JavaScript数组开发

2018-10-11 09:40:53

前端JavaScript编程语言

2024-04-11 08:30:05

JavaScript数组函数

2015-07-06 09:59:56

JavaScript私有成员

2021-11-08 10:58:08

变量依赖图排序

2023-04-26 15:19:36

JavaScripMap数组

2020-12-08 08:07:41

JavaScript中等分数组

2022-01-21 10:58:39

JavaScriptGolangPython

2019-04-23 15:20:26

JavaScript对象前端

2009-11-24 17:45:47

PHP数组排序函数ar

2011-03-21 12:41:41

JavaScript

2021-06-03 10:00:47

JavaScript 前端数克隆对象

2020-08-23 11:32:21

JavaScript开发技术

2016-08-03 17:23:47

javascripthtml前端

2021-05-17 14:02:38

Swift 多重排序

2022-03-15 07:55:09

JavaScript线性仪表图开发

2017-04-06 14:10:08

JavaScript数组排序

2021-03-26 23:41:19

JavaScript对象开发

2022-06-01 08:12:32

JS类数组对象
点赞
收藏

51CTO技术栈公众号