首页 > 解决方案 > 使用 JavaScript reduce 更新并添加到对象数组

问题描述

我正在尝试解决 JavaScript 中的一个问题,并相信使用该reduce方法将是最优雅的。我有一组看起来像这样的对象:

let existingLots = [
    {
        id: 1,
        title: 'one',
        colour: 'red',
        speed: 100
    },
    {
        id: 2,
        title: 'two',
        colour: 'blue',
        speed: 70
    },
    {
        id: 3,
        title: 'three',
        colour: 'white',
        speed: 120
    },
    {
        id: 4,
        title: 'four',
        colour: 'yellow',
        speed: 90
    },
]

另一个看起来像这样的数组:

let newLots = [
    {
        id: 1,
        title: 'one',
        colour: 'orange',
        speed: 100,
        owner: 'Ted'
    },
    {
        id: 2,
        title: 'two',
        colour: 'blue',
        speed: 75
    },
    {
        id: 3,
        title: 'three updated',
        colour: 'white',
        speed: 120,
    },
    {
        id: 4,
        title: 'four',
        colour: 'yellow',
        speed: 90
    },
    {
        id: 5,
        title: 'five',
        colour: 'green',
        speed: 50
    },
]

如您所见,一些 id 之间存在重叠。我想更新existingLots数组,以便如果一个对象与数组id中的一个共享相同newLots,则该对象将使用其对应对象中的任何新属性/值进行更新newLots。另外,我希望将不在其中的任何对象newLots(即带有idof 的对象)添加到数组中。5existingObjectsexistingObjects

我尝试了以下方法,但没有达到预期的结果:

const res = existingLots.reduce((acc, obj) => {
    let updatedObj = newLots.filter(newLot => newLot.id === obj.id);
    // if object exists in currentLots, merge it
    if(updatedObj) {
        [...acc, {...obj, ...updatedObj}]
    } else {
        let newObj = !newLots.filter(newLot => newLot.id === obj.id);
        [...acc, {...newObj}]
    }
    return acc
}, [])

我是 JavaScript 数组方法的新手,因此不胜感激。

标签: javascriptarraysobjectreduce

解决方案


1) You are using filter which will return an array of filter elements

The filter() method creates a new array with all elements that pass the test implemented by the provided function. - MDN

2) This code just push/add all objects after the last element in the array and then discarded since you are not storing them anywhere

[...acc, {...obj, ...updatedObj}]

SOLUTION: You can use forEach to loop over the newLots array and add data to existingLots element

newLots.forEach((newLot) => {
  let objExist = existingLots.find((o) => o.id === newLot.id);
  if (objExist) {
    for (let key in newLot) objExist[key] = newLot[key];
  } else existingLots.push(newLot);
});

or

newLots.forEach((newLot) => {
  let index = existingLots.findIndex((o) => o.id === newLot.id);
  if (index !== -1) existingLots[index] = { ...existingLots[index], ...newLot };
  else existingLots.push(newLot);
});

let existingLots = [
  {
    id: 1,
    title: "one",
    colour: "red",
    speed: 100,
  },
  {
    id: 2,
    title: "two",
    colour: "blue",
    speed: 70,
  },
  {
    id: 3,
    title: "three",
    colour: "white",
    speed: 120,
  },
  {
    id: 4,
    title: "four",
    colour: "yellow",
    speed: 90,
  },
];

let newLots = [
  {
    id: 1,
    title: "one",
    colour: "orange",
    speed: 100,
    owner: "Ted",
  },
  {
    id: 2,
    title: "two",
    colour: "blue",
    speed: 75,
  },
  {
    id: 3,
    title: "three updated",
    colour: "white",
    speed: 120,
  },
  {
    id: 4,
    title: "four",
    colour: "yellow",
    speed: 90,
  },
  {
    id: 5,
    title: "five",
    colour: "green",
    speed: 50,
  },
];

newLots.forEach((newLot) => {
  let index = existingLots.findIndex((o) => o.id === newLot.id);
  if (index !== -1) existingLots[index] = { ...existingLots[index], ...newLot };
  else existingLots.push(newLot);
});

console.log(existingLots);


推荐阅读