如何对数字数组进行连续排序和重新排序以允许重复值

时间:2018-12-20 22:44:02

标签: javascript arrays reactjs typescript

有一个奇怪的问题要解决,那就是将我的大脑束缚在试图可视化的过程中。我有一个数组对象来维护,就像这样:

let approvers = [{order:1, dueDate: someDate},{order:2, dueDate: someDate}, 
                 {order:3, dueDate: someDate},{order:4, dueDate: someDate}];

通过用户界面,用户可以决定将批准者的顺序调整为与其他批准者相同,以允许任务并行运行,从而使集合看起来像这样

let approvers = [{order:1, dueDate: someDate},{order:1, dueDate: someDate}, 
                 {order:3, dueDate: someDate},{order:4, dueDate: someDate}];

发生这种情况时,我需要一个函数来更新集合以将订单值设置为连续的,但允许重复,因此最终看起来像这样

let approvers = [{order:1, dueDate: someDate},{order:1, dueDate: someDate}, 
                 {order:2, dueDate: someDate},{order:3, dueDate: someDate}];

另一种可能性是,最终用户可以从集合中删除批准者,使其看起来像这样

let approvers = [{order:1, dueDate: someDate},{order:2, dueDate: someDate}, 
                 {order:4, dueDate: someDate}];

当发生这种情况时,我需要功能来更新集合,使其看起来像这样

let approvers = [{order:1, dueDate: someDate},{order:2, dueDate: someDate}, 
                 {order:3, dueDate: someDate}];

我使用矩进行日期操作,使用lodash进行基本排序

在下面的代码中mo = moment lo = lodash

 private reorderApprovers(apps: IApprover[]): IApprover[] {
    let tempApps: IApprover[] = lo.orderBy(apps, ['order'], ['asc']);
    let previousOrder: number = 1;
    tempApps.forEach((app, index) => {
      if (index != 0) {
        if (app.order != previousOrder && app.order != previousOrder + 1) {
          app.order = previousOrder + 1;
          previousOrder++;
        }
      }
      else {
        app.order = previousOrder;
        previousOrder++;
      }
    });     
    return tempApps;
  }

2 个答案:

答案 0 :(得分:1)

我认为您可以通过此作业做您想做的事

tempApps = [...apps]
    .sort((a, b) => a.order - b.order)
    .forEach((a, i) => a.order = !i ? 1 
                       : apps[i-1].order + (a.order > apps[i-1].order));

这首先创建一个浅表副本(以免改变原始数组);然后该副本按order排序;最后,order的值用以下逻辑进行校正:第一个应具有order 1,而下一个应具有等于前一个order或更多的order

答案 1 :(得分:0)

感谢@trincot使我的头部朝正确的方向运动,这是对我有用的解决方案

  private reorderApprovers(apps: IApprover[]): IApprover[] {
    let tempApps: IApprover[] = lo.orderBy(apps, ['order'], ['asc']);
    let nextOrder: number = 1;
    let previousOrder: number = 1;
    tempApps.forEach((app, index) => {
      if (index != 0) {
        if (app.order != previousOrder && app.order != nextOrder) {
          previousOrder = nextOrder;
          nextOrder++;
          app.order = nextOrder;
        }
      }
      else {
        app.order = nextOrder;
        nextOrder++;
      }
    });     
    return tempApps;
  }