对一个对象数组进行多维排序

之前做优惠券的时候有用到,而且一直对 sort 的顺序似是而非,所以做一个总结。

对以下数组进行排序,要求:价格低排前面、同价格邮费低在前、前两个相等销量高的在前。

const arr = [
  { name: '商品01', price: 123.0, sales: 123, postage: 19 },
  { name: '商品02', price: 124.0, sales: 123, postage: 0 },
  { name: '商品03', price: 123.0, sales: 133, postage: 29 },
  { name: '商品04', price: 125.0, sales: 123, postage: 9 },
  { name: '商品05', price: 123.0, sales: 143, postage: 19 }
];
复制代码

对 sort 函数简单记忆:返回结果大于 0,交换位置,否则不变。

利用 js 中 0 为 false 的特性,短路写法可以一行搞定:

arr.sort((a, b) => {
  return a.price - b.price || a.postage - b.postage || b.sales - a.sales;
});
// arr:
[
{"name":"商品05","price":123,"sales":143,"postage":19},
{"name":"商品01","price":123,"sales":123,"postage":19},
{"name":"商品03","price":123,"sales":133,"postage":29},
{"name":"商品02","price":124,"sales":123,"postage":0},
{"name":"商品04","price":125,"sales":123,"postage":9}
]
复制代码

虽然这也不麻烦,但是能不能更方便一点?

实现一个对象数组多维排序函数:

const keys = ['price', 'postage', 'sales']; // 传入要排序的 key,优先级从高到低
const orders = [1, 1, -1]; // 每个 key 的排序方式,1 正序,-1 倒序

function multiSort(array, keys, orders) {
  if (!keys) return array;
  if (!orders) {
    orders = Array.from({ length: keys.length }, () => 1); // 默认从小到大排序
  }
  
  return [...array].sort((a, b) => {
    for (let [index, key] of keys.entries()) {
      if (a[key] - b[key] === 0) continue; // 如果当前维度条件相等,判断下一个维度
      return (a[key] - b[key]) * orders[index];
    }
    return 0; // 全部相等返回 0
  });
}

const arr1 = multiSort(arr, keys, orders)
// arr1:
[
{"name":"商品05","price":123,"sales":143,"postage":19},
{"name":"商品01","price":123,"sales":123,"postage":19},
{"name":"商品03","price":123,"sales":133,"postage":29},
{"name":"商品02","price":124,"sales":123,"postage":0},
{"name":"商品04","price":125,"sales":123,"postage":9}
]
复制代码

其实前端能用到排序的机会并不多,一般列表都有分页,排序都是把条件传到后端。但是对于优惠券,或者其他数量一次性返回的列表进行排序,就需要自己上场了。

当然,这个函数是不严谨的:数组是浅拷贝,没有 keys 和 orders 长度不一致的防呆功能,没有参数类型验证。大型项目中这些都是要考虑的问题。

转载于:https://juejin.im/post/5cbd215a5188250a51083bd2

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值