JS 中创建自定义排序方法

为了保证的可读性,本文采用意译而非直译。

一般情况咱们排序大都按数字或字母顺序,但也有一些情况下,咱们可能需要自定义排序顺序。

在此之前先简单介绍一下 reduce 方法:

语法:arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

callback:执行数组中每个值的函数,包含四个参数:

accumulator:累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue(见于下方)。

currentValue:数组中正在处理的元素。

currentIndex (可选):数组中正在处理的当前元素的索引。如果提供了initialValue,则起始索引号为0,否则为1。

array(可选): 调用 reduce() 的数组

initialValue(可选):作为第一次调用 callback 函数时的第一个参数的值。如果没有提供初始值,则将使用数组中的第一个元素。在没有初始值的空数组上调用 reduce 将报错。

rudeuce 过程描述:

回调函数第一次执行时,accumulator 和currentValue的取值有两种情况:如果调用reduce()时提供了initialValue,accumulator取值为initialValue,currentValue取数组中的第一个值;如果没有提供 initialValue,那么accumulator取数组中的第一个值,currentValue取数组中的第二个值。

回到原文:

如下面的例子所示,咱们想让 inProgress 在第一位,接着是 todo,然后是 done。

const tasks = [
  {id:1, title: 'Job A', status: 'done'},
  {id:2, title: 'Job B', status: 'inProgress'},
  {id:3, title: 'Job C', status: 'todo'},
  {id:4, title: 'Job D', status: 'inProgress'},
  {id:5, title: 'Job E', status: 'todo'}
]

首先按照所需的排序顺序创建一个数组。

const sortBy = ['inProgress', 'todo', 'done']

使用reduce来创建一个函数,参数为一个数组,最后输出以数组项为键,索引为值,如 {inProgress:0,todo:1,done:2}。

const sortByObject = data => data.reduce(
  (obj,item,index) => ({
    ...obj,
    [item]:index
}), {}
)
console.log(sortByObject(sortBy))
/* {inProgress: 0, todo: 1, done: 2} */

这样就有了排序设置,咱们可以将它与一个可重用的函数放在一起,该函数传入一个数组(data)、一个sortby数组和一个sortField,这样咱们就知道要在哪个字段上排序:

const customSort = ({data, sortBy, sortField}) => {
  const sortByObject = sortBy.reduce(
  (obj, item, index) => ({
      ...obj,
      [item]: index
  }), {})
  return data.sort((a, b) => sortByObject[a[sortField]] - sortByObject[b[sortField]])
}

console.log(customSort({data:tasks, sortBy, sortField: ‘status’}))
这样就可以按照咱们的自定义顺序排序,不过还有一个问题,如果列表中有一个status不同的项(不在咱们的排序顺序中),就会出现问题。因此,为了处理这个问题,咱们需要设置一个默认的sort字段来捕获排序中不需要的所有项。

const tasksWithDefault = tasks.map(item => (
  {  
    ...item,
    sortStatus: sortBy.includes(item.status) ? item.status:'other'
  })
 )

这次传递的是更新后的sort字段,那么现在就有了正确的排序顺序,列表底部还有包含状态为 other 的项目。

完整代码:

const tasks = [
  { id: 1, title: "Job A", status: "done" },
  { id: 2, title: "Job B", status: "inProgress" },
  { id: 3, title: "Job C", status: "todo" },
  { id: 3, title: "Job D", status: "onHold" },
  { id: 4, title: "Job E", status: "inProgress" },
  { id: 5, title: "Job F", status: "todo" }
];
const sortBy = ["inProgress", "todo", "done"];
 
const customSort = ({ data, sortBy, sortField }) => {
  const sortByObject = sortBy.reduce(
    (obj, item, index) => ({
      ...obj,
      [item]: index
    }),
    {}
  );
  return data.sort(
    (a, b) => sortByObject[a[sortField]] - sortByObject[b[sortField]]
  );
};
const tasksWithDefault = tasks.map(item => ({
 ...item,
 sortStatus: sortBy.includes(item.status) ? item.status : "other"
}));
console.log(
 customSort({
   data: tasksWithDefault,
   sortBy: [...sortBy, "other"],
   sortField: "sortStatus"
 })
);

运行结果:

最后

分享移动开发与微信小程序开发该做哪些!其中有哪些关键的技术点!需要下图学习教程的欢迎加入web前端交流群:854591759获取!

点击链接加入群聊【web前端交流群】:

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值