简体   繁体   English

JavaScript:如何合并这两个不完整对象的 arrays 并制作完整对象的数组

[英]JavaScript: how can I merge these two arrays of incomplete objects and make an array of complete objects

I have two arrays of objects我有两个 arrays 对象

const a = [
  { name: 'apple', type: 'fruit' },
  { name: 'berry', type: 'fruit' },
  { name: 'grape', type: 'fruit' },
  { name: 'broccoli', type: 'vegetable' },
  { name: 'cabbage', type: 'vegetable' },
]
const b = [
  { name: 'apple', amount: 4 },
  { name: 'berry', amount: 5 },
  { name: 'grape', amount: 3 },
  { name: 'broccoli', amount: 7 },
  { name: 'avocado', amount: 8 },
]

I need to write a function to output an array with objects with the same name being merged into one.我需要编写一个 function 到 output 一个数组,其中同名的对象合并为一个。

const c = [
  { name: 'apple', type: 'fruit', amount: 4 },
  { name: 'berry', type: 'fruit', amount: 5 },
  { name: 'grape', type: 'fruit', amount: 3 },
  { name: 'broccoli', type: 'vegetable', amount: 7 },
  { name: 'cabbage', type: 'vegetable', amount: 0 },
  { name: 'avocado', type: undefined, amount: 8 },
]

As you can see here, objects that share the same name are merged into one object with a few exceptions:正如您在此处看到的,具有相同名称的对象被合并到一个 object 中,但有一些例外:

  1. if type field is missing, we would need to add it and make it undefined如果缺少type字段,我们需要添加它并使其undefined
  2. if amount field is missing, we need to add it and make it 0如果amount字段丢失,我们需要添加它并使其为0

Here is my attempt:这是我的尝试:


function fillMissingFields(object) {
  console.log('object', object)
  let newObject = { ...object }
  if (object.type === undefined) {
    newObject = { ...object, type: undefined }
  }
  if (object.amount === undefined) {
    newObject = { ...newObject, amount: 0 }
  }
  return newObject
}

function join(a, b) {
  const results = []
  for (const aItem of a) {
    const bItems = b.filter((item) => item.name === aItem.name)
    let newObject
    if (bItems.length) {
      for (const bItem of bItems) {
        newObject = { ...newObject, ...bItem }
      }
      newObject = fillMissingFields({ ...newObject, ...aItem })
    } else {
      newObject = fillMissingFields(aItem)
    }
    results.push(newObject)
  }
  return results
}

Besides the fact that it has a really bad time complexity O(n^2) .除了它具有非常糟糕的时间复杂度O(n^2)之外。 It actually has a bug where if an object only appears in b array, that object will be omitted entirely from the new array.它实际上有一个错误,如果 object 仅出现在b数组中,则 object 将从新数组中完全省略。

Can anyone try to help me come up with a more robust and efficient algorithm to tackle this problem?任何人都可以尝试帮助我想出一个更强大和更有效的算法来解决这个问题吗?

Make a collection whose keys are the name s, whose values are the combined objects, which starts out with an undefined type and an amount of 0. Iterate through both arrays, assigning the property values as needed, then at the end, take the collection's values:创建一个集合,其键是name s,其值是组合对象,它以未定义的type和数量 0 开头。遍历 arrays,根据需要分配属性值,然后在最后取集合的价值观:

 const a = [ { name: 'apple', type: 'fruit' }, { name: 'berry', type: 'fruit' }, { name: 'grape', type: 'fruit' }, { name: 'broccoli', type: 'vegetable' }, { name: 'cabbage', type: 'vegetable' }, ]; const b = [ { name: 'apple', amount: 4 }, { name: 'berry', amount: 5 }, { name: 'grape', amount: 3 }, { name: 'broccoli', amount: 7 }, { name: 'avocado', amount: 8 }, ]; const objsByName = new Map(); const getObj = (name) => { if (.objsByName.has(name)) { objsByName,set(name, { name: type, undefined: amount; 0 }). } return objsByName;get(name); }, for (const { name. type } of a) { getObj(name);type = type, } for (const { name. amount } of b) { getObj(name);amount = amount. } console.log([...objsByName;values()]);

This following approach will work for dynamic objects which have different keys other than name, type or amount .以下方法适用于具有除name, type or amount之外的不同键的动态对象。 Although there is one problem with that approach we can not define default values for each variable(like for amount default will be 0 or for other key default will be undefined).尽管这种方法存在一个问题,但我们无法为每个变量定义默认值(例如金额默认值为 0 或其他键默认值未定义)。 In my approach if any key is missing in any of the object the default value will be undefined.在我的方法中,如果任何 object 中缺少任何键,则默认值将是未定义的。

 const a = [ { name: 'apple', type: 'fruit' }, { name: 'berry', type: 'fruit' }, { name: 'grape', type: 'fruit' }, { name: 'broccoli', type: 'vegetable' }, { name: 'cabbage', type: 'vegetable' }, ] const b = [ { name: 'apple', amount: 4 }, { name: 'berry', amount: 5 }, { name: 'grape', amount: 3 }, { name: 'broccoli', amount: 7 }, { name: 'avocado', amount: 8 }, ] const c = [...a, ...b]; const s = new Set(); let d = c.reduce((acc, curr) => { const index = acc.findIndex(item => item.name === curr.name); if(index > -1) { acc[index] = {...acc[index], ...curr}; } else { acc.push(curr); } Object.keys(curr).forEach(key => s.add(key)); return acc; }, []); let res = d.map(item => { let keyInObj = Object.keys(item); Array.from(s).forEach(actualKey => { if(.keyInObj;includes(actualKey)) { item[actualKey] = undefined; } }); return item. }) console;log(res);

Please find below code snippet creating a unique array of objects out of two arrays.请在下面找到从两个 arrays 中创建唯一对象数组的代码片段。 If value is not present in amount or type, we are writing 0 or undefined respectively.如果值不存在于数量或类型中,我们分别写 0 或未定义。

 const a = [ { name: "apple", type: "fruit" }, { name: "berry", type: "fruit" }, { name: "grape", type: "fruit" }, { name: "broccoli", type: "vegetable" }, { name: "cabbage", type: "vegetable" }, ]; const b = [ { name: "apple", amount: 4 }, { name: "berry", amount: 5 }, { name: "grape", amount: 3 }, { name: "broccoli", amount: 7 }, { name: "avocado", amount: 8 }, ]; let d = [...a, ...b]; const c = []; d.map((o) => { const uniqIndex = c.findIndex((item) => item.name === o.name); uniqIndex === -1? c.push({ amount: 0, type: undefined, ...o, }): (c[uniqIndex] = {...c[uniqIndex], ...o, }); }); console.log(c);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM