比较两个对象数组,然后用另一个替换对象

时间:2020-06-29 19:17:07

标签: javascript ecmascript-6

我有一个工作函数,可将对象customData的数组追加到另一个对象testData的末尾。如果两个数组中都出现具有相同属性name值的对象,则将删除testData对象,并在结果数组中将其替换为customData对象。 customData对象具有上一个testData对象的顺序。

但是这是我的尝试,我想知道是否有更好的方法可以轻松读取(es6)?

谢谢

https://codesandbox.io/s/recursing-river-bdp5k?file=/src/App.js

export default function App() {
  const testData = [
    { display: "1", name: "TEST1" },
    { display: "2", name: "TEST2" }
  ];

  const customData = [
    { display: "CUSTOM_1", name: "TEST1", custom: "YES" },
    { display: "CUSTOM_3", name: "TEST3", custom: "YES" }
  ];

  let i = 0;
  const newTestData = testData;
  let newCustomData = customData;

  while (i < customData.length) {
    const view = customData[i];
    const index = testData.findIndex(x => x.name === view.name);

    if (index >= 0) {
      newTestData[index] = customData[i];
      newCustomData.splice(i, 1);
    }
    i += 1;
  }

  const concatData = newTestData.concat(newCustomData);
  console.log(concatData)

  return null;
}

3 个答案:

答案 0 :(得分:0)

Array#concat不会使数组发生突变,因此无需将它们分配给新变量(无论如何也不会复制数组)。如果您想使用简洁的ES6代码,请跳过while循环-有许多等效项。这是一个示例:

您没有定义“更好的方式”,但我将其解释为“针对性能和可读性进行了最优化”。在下面的方法中,我使用一个步骤填充地图,然后使用另一遍在需要时用customData覆盖地图条目,最后使用Object.values()(技术上是第三遍)来生成结果。与您的O(n ^ 2)实现相比,这是O(n)(无嵌套循环)。

const testData = [
  { display: "1", name: "TEST1" },
  { display: "2", name: "TEST2" }
];

const customData = [
  { display: "CUSTOM_1", name: "TEST1", custom: "YES" },
  { display: "CUSTOM_3", name: "TEST3", custom: "YES" }
];

let map = {};
testData.forEach(item => map[item.name] = item);
customData.forEach(item => map[item.name] = item);
const result = Object.values(map);

console.log(result);

在很多情况下(包括此情况),您都有一堆由唯一键(例如name)标识的数据,您确实应该使用对象作为开始。任何时候需要数组时,都有Object.values()Object.keys()

答案 1 :(得分:0)

代码背后的逻辑是正确的。 这几乎是相同的,但是没有显式循环:

 const testData = [
  { display: "1", name: "TEST1" },
  { display: "2", name: "TEST2" }
];

const customData = [
  { display: "CUSTOM_1", name: "TEST1", custom: "YES" },
  { display: "CUSTOM_3", name: "TEST3", custom: "YES" }
];


Array.prototype.uniqueWith = function(comparator) {
  return this.reduce((a, c, i) => {
    const j = a.slice(i+1).findIndex(e => comparator(e, c));
    if(j !== -1) {
      a[i] = a[i+j+1];
      a.splice(i+j+1, 1);
    }
    return a;
  }, this);
}

const eqByName = (a, b) => a.name === b.name;

const result = [...testData, ...customData].uniqueWith(eqByName);
console.log(result);

请注意,扩展Array原型可能不是最好的主意,因此您可以创建单独的函数,该函数将级联数组作为参数。

答案 2 :(得分:0)

这是您要寻找的功能吗?

const result = App(myTestData(), myCustData());
console.log(result);

function App(testData, custData) {

  // `indByName` returns index (in arr) of obj w/ matching name (or -1 if no match)
  const indByName = (arr, name) => 
    ind = arr.findIndex(o => o.name === name);

  let custInd; // Identifier for output of `indByName`
  const custDataClone = custData.slice(); // Prevents mutating `custData`

  return testData.map(item => (

    // Uses indByName to get index of corresponding custom item
    custInd = indByName(custDataClone, item.name),

    // Moves corresponding custom item into testData if appropriate
    custInd > -1 ? custDataClone.splice(custInd, 1)[0] : item

  // Appends remaining items from custDataClone to the new array
  )).concat(custDataClone)
}

function myTestData(){
  return [
    { display: "1", name: "TEST1" },
    { display: "2", name: "TEST2" }
  ];
}

function myCustData(){
  return [
    { display: "CUSTOM_1", name: "TEST1", custom: "YES" },
    { display: "CUSTOM_3", name: "TEST3", custom: "YES" }
  ];
}

相关问题