合并和比较

时间:2018-08-01 21:32:03

标签: javascript node.js

我写了一个逻辑,以合并message2变量中的所有批次。如果有重复的批次名称(AA,BB),它将合并所有批次并计算行数。

var message2 = {
    Batches: [ 
        {Batch: "AA", Lines: 1 },
        {Batch: "BB", Lines: 2 },
        {Batch: "BB", Lines: 6 }
    ]
}

成为:

[ { Batch: 'AA', Lines: 1 }, { Batch: 'BB', Lines: 8 } ]

这是通过reduce()方法完成的。

forEach循环中,它循环所有mergedBatches(合并后),并与Worker变量中的批次进行比较。如果Worker行多于mergedBatches行,然后将mergedBatches设置为与Worker行匹配,它将需要找到相同的批次名称。

var message2 = {
    Batches: [ 
        {Batch: "AA", Lines: 1 },
        {Batch: "BB", Lines: 2 },
        {Batch: "BB", Lines: 6 }
    ]
}

var Worker = { 
    Batches: [
        {Batch: "AA", Lines: 2 },
        {Batch: "BB", Lines: 3 },
    ]
}

var mergedBatches = message2.Batches.reduce((acc, obj)=>{
    var existObj = acc.find(b => b.Batch === obj.Batch);

    if(existObj) {
      existObj.Lines += obj.Lines;
      return acc;
    }

    acc.push({Batch: obj.Batch, Lines: obj.Lines});
    return acc;
},[]);

mergedBatches.forEach((b) => {
    var workerBatch = Worker.Batches.find(wB => wB.Batch === b.Batch);
    if (b.Lines >= workerBatch.Lines) {
        b.Lines = workerBatch.Lines;
    }
});


console.log(mergedBatches)

最终结果按预期运行:

[ { Batch: 'AA', Lines: 1 }, { Batch: 'BB', Lines: 3 } ]

是否有一种方法可以重构此代码以使其更具可读性?

3 个答案:

答案 0 :(得分:0)

这更加直接,应该更快:

const mergeBatches = (message) => {
  const obj = {};

  for (let i = message.Batches.length; i--;) {
    const current = message.Batches[i];

    if (current.Batch in obj) {
      obj[current.Batch] += current.Lines;
    } else {
      obj[current.Batch] = current.Lines;
    }
  }

  const arr = [];

  for (let key in obj) {
    arr.push({
      Batch: key,
      Lines: obj[key]
    })
  }

  return arr;
}

您正在学习功能模式确实很不错,但是它们并不总是最快的。

例如,您的代码中有acc.find。在幕后,find每次执行函数时都在数组acc上进行迭代,这使得复杂度为O(n * n)我认为是这样,如果我错了,有人会发表评论< / em>。

在我提供的函数中,您仅对Batches数组进行一次迭代,这使得该O(n)。

答案 1 :(得分:0)

从您当前的结构来看,这将是获得预期结果的另一种方式:

const merged = {};
message2.Batches.forEach(b => {
  if(merged[b.Batch]) {
    merged[b.Batch].Lines += b.Lines;
  } else {
    merged[b.Batch] = b;
  }
});

const result = [];
Worker.Batches.forEach(b => {
  if (merged[b.Batch] && merged[b.Batch].Lines > b.Lines) {
    merged[b.Batch].Lines = b.Lines;
  }
  result.push(merged[b.Batch]);
});

// Output
[{ "Batch": "AA", "Lines": 1 }, { "Batch": "BB", "Lines": 3 }]

答案 2 :(得分:0)

这是一个简短的版本:

  1. 如果mergedBatches不应包含对message2.Batches条目的引用,则可以使用解构:acc.push({ ...cur });
  2. 单行if/else应该更易读,没有括号;
  3. 在最新情况下进行空检查:find可以返回未定义的值。

const message2 = {
  Batches: [ 
    {Batch: "AA", Lines: 1 },
    {Batch: "BB", Lines: 2 },
    {Batch: "BB", Lines: 6 }
  ]
}

const Worker = { 
  Batches: [
    {Batch: "AA", Lines: 2 },
    {Batch: "BB", Lines: 3 },
  ]
}

const mergedBatches = message2.Batches.reduce((acc, cur) => {
  const prev = acc.find(x => x.Batch === cur.Batch)

  if (prev) prev.Lines += cur.Lines
  else acc.push(cur)

  return acc
}, [])

mergedBatches.forEach((mb) => {
  const wb = Worker.Batches.find(x => x.Batch === mb.Batch)

  if (wb && wb.Lines < mb.Lines ) mb.Lines = wb.Lines
})

console.log(mergedBatches)