关于javascript:如何在JavaScript中对对象数组进行排序

44次阅读

共计 4467 个字符,预计需要花费 12 分钟才能阅读完成。

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

点赞再看,养成习惯

本文 GitHub https://github.com/qq44924588… 上曾经收录,更多往期高赞文章的分类,也整顿了很多我的文档,和教程材料。欢送 Star 和欠缺,大家面试能够参照考点温习,心愿咱们一起有点货色。

最近开源了一个 Vue 组件,还不够欠缺,欢送大家来一起欠缺它,也心愿大家能给个 star 反对一下,谢谢各位了。

github 地址:https://github.com/qq449245884/vue-okr-tree

如果须要按特定程序对对象数组进行排序,咱们很有可能会间接找个 JS 库来用。其实大可不必,JS 原生中的 Array.sort就能间接一些简单又丑陋的排序。

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

根本数组排序

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

const foo = [9, 1, 4, 'zebroid', 'afterdeck'];
foo.sort(); // returns [ 1, 4, 9, 'afterdeck', 'zebroid']

const bar = [5, 18, 32, new Set, { user: 'Eleanor Roosevelt'}];
bar.sort(); // returns [ 18, 32, 5, { user: 'Eleanor Roosevelt'}, Set {}]

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

须要留神的是,Array.sort会更改原数组。

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

为防止这种状况,咱们能够创立要排序的数组的新实例,而后在新的数组上进行批改。这里能够应用 Array.slice它返回是一个新的数组实例。

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

咱们还能够应用 ES6 中的开展运算符来做:

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

在两种状况下,输入是雷同的:

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

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

应用比拟函数进行排序

假如 foobarcompare 函数要比拟的两个元素,compare函数的返回值设置如下:

  1. 小于 0foobar之前
  2. 大于 0barfoo之前
  3. 等于 0foobar彼此放弃不变。

来看一个简略的示例:

const nums = [79, 48, 12, 4];

function compare(a, b) {if (a > b) return 1;
  if (b > a) return -1;

  return 0;
}

nums.sort(compare);
// => 4, 12, 48, 79

咱们能够略微重构一下:

function compare(a, b) {return a - b;}

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

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

如何对对象数组进行排序

当初,咱们来按一下对对象数组的排序。假如有上面的 singers 数组:

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

咱们能够应用 compare函数,而后依据 singers 中的 band 字段来进行排序。

function compare(a, b) {// 应用 toUpperCase() 疏忽字符大小写
  const bandA = a.band.toUpperCase();
  const bandB = b.band.toUpperCase();

  let comparison = 0;
  if (bandA > bandB) {comparison = 1;} else if (bandA < bandB) {comparison = -1;}
  return comparison;
}

singers.sort(compare);

/* returns [{ name: 'Steven Tyler', band: 'Aerosmith',  born: 1948},
  {name: 'Stevie Nicks', band: 'Fleetwood Mac', born: 1948},
  {name: 'Kurt Cobain', band: 'Nirvana', born: 1967},
  {name: 'Karen Carpenter', band: 'The Carpenters', born: 1950}
] */

如果要让下面的程序相同,能够这么做:

function compare(a, b) {
  ...

  // 乘以 - 1 来反转返回值
  return comparison * -1;
}

创立一个动静排序函数

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

咱们创立一个排序函数,能够应用该函数对一组对象进行排序,这些对象的值能够是字符串或数字。该函数有两个参数 - 咱们要排序的键和返回后果的程序(即升序或降序):

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

function compareValues(key, order = 'asc') {return function innerSort(a, b) {if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) {
      // 该属性在任何一个对象上都不存在
      return 0;
    }

    const varA = (typeof a[key] === 'string')
      ? a[key].toUpperCase() : a[key];
    const varB = (typeof b[key] === 'string')
      ? b[key].toUpperCase() : b[key];

    let comparison = 0;
    if (varA > varB) {comparison = 1;} else if (varA < varB) {comparison = -1;}
    return ((order === 'desc') ? (comparison * -1) : comparison
    );
  };
}

应用:

// 数组按 `band` 排序,默认为升序
singers.sort(compareValues('band'));

// 数组按 `band` 降序排序
singers.sort(compareValues('band', 'desc'));

// 数组按 `name` 升序排序
singers.sort(compareValues('name'));

// 数 组 born 降序排序
singers.sort(compareValues('born', 'desc'));

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

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

最初,你能够依据本人需要来调整下面的函数。

String.prototype.localeCompare()

在下面的示例中,咱们心愿可能对对象数组进行排序,其值能够是字符串或数字。然而,如果咱们晓得解决值是字符串的对象,则能够应用 JS 的 localeCompare 办法

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

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

['bjork', 'Bjork', 'Björk'].sort((a, b) => a.localeCompare(b));
//  ['bjork', 'Bjork', 'Björk']

依据 compareValues 函数,咱们能够这么写:

function compareValues(key, order = 'asc') {return function innerSort(a, b) {if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) return 0;
    const comparison = a[key].localeCompare(b[key]);

    return ((order === 'desc') ? (comparison * -1) : comparison
    );
  };
}

总结

下面就是应用一般 JS 函数对对象数组排序的简短的介绍。只管许多库都提供了这种动静排序能力,但咱们本人实现这个办法其实也不信。另外,理解幕后产生了对咱们来说并没有害处。

明天就跟大家分享到这里了,感激大家的观看,咱们下期再见。


代码部署后可能存在的 BUG 没法实时晓得,预先为了解决这些 BUG,花了大量的工夫进行 log 调试,这边顺便给大家举荐一个好用的 BUG 监控工具 Fundebug。

原文:https://www.sitepoint.com/sor…

交换

文章每周继续更新,能够微信搜寻「大迁世界」第一工夫浏览和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 曾经收录,整顿了很多我的文档,欢送 Star 和欠缺,大家面试能够参照考点温习,另外关注公众号,后盾回复 福利,即可看到福利,你懂的。

正文完
 0