合并来自两个不同对象数组的具有相应键值的对象

时间:2018-09-29 03:55:02

标签: javascript arrays object ecmascript-6 lodash

我有两个具有多个对象的数组

[
     {
         "name":"paul",
         "employee_id":"8"
     }
]

[
     {
         "years_at_school": 6,
         "department":"Mathematics",
         "e_id":"8"
     }
]

如何通过ES6或Lodash实现以下目标?

[
     {
         "name":"paul",
         "employee_id":"8"
         "data": {
             "years_at_school": 6
             "department":"Mathematics",
             "e_id":"8"
         }
     }
]

我可以合并,但不确定如何创建新的子对象并将其合并。

我尝试过的代码:

school_data = _.map(array1, function(obj) {
    return _.merge(obj, _.find(array2, {employee_id: obj.e_id}))
})

这像这样合并到顶层数组(这不是我想要的):

{
     "name":"paul",
     "employee_id":"8"
     "years_at_school": 6
     "department":"Mathematics",
     "e_id":"8"
 }

这两个之间的连接器是"employee_id""e_id"

必须考虑到每个数组中它们可以是1000个对象,并且匹配这些对象的唯一方法是使用"employee_id""e_id"

5 个答案:

答案 0 :(得分:1)

为了匹配employee_ide_id,您应该遍历第一个数组并创建一个键为employee_id的对象。然后,您可以遍历第二个数组并将数据添加到有问题的特定ID中。这是一个向每个数组添加一个额外项目的示例:

let arr1 = [
    {
        "name":"mark",
        "employee_id":"6"
    },
    {
        "name":"paul",
        "employee_id":"8"
    }
]

let arr2 = [
    {
        "years_at_school": 6,
        "department":"Mathematics",
        "e_id":"8"
    },
    {
        "years_at_school": 12,
        "department":"Arr",
        "e_id":"6"
    }
    
]

// empObj will be keyed to item.employee_id 
let empObj = arr1.reduce((obj, item) => {
    obj[item.employee_id] = item
    return obj
}, {})

//  now lookup up id and add data for each object in arr2
arr2.forEach(item=>
    empObj[item.e_id].data = item
)

// The values of the object will be an array of your data
let merged = Object.values(empObj)
console.log(merged)

答案 1 :(得分:1)

如果执行两个嵌套的O(n)循环(map + find),最终将获得O(n ^ 2)性能。一个典型的替代方法是创建中间索引结构,因此整个对象为O(n)。 lodash的功能性方法:

const _ = require('lodash');
const dataByEmployeeId = _(array2).keyBy('e_id');
const result = array1.map(o => ({...o, data: dataByEmployeeId.get(o.employee_id)}));

答案 2 :(得分:0)

希望这对您有帮助:

var mainData = [{
   name: "paul",
   employee_id: "8"
}];

var secondaryData = [{
  years_at_school: 6,
  department: "Mathematics",
  e_id: "8"
}];

var finalData = mainData.map(function(person, index) {
  person.data = secondaryData[index];
  return person;
});

抱歉,我还修复了第二个对象中丢失的昏迷,并更改了一些其他内容。

使用最新的Ecmascript版本:

const mainData = [{
   name: "paul",
   employee_id: "8"
}];

const secondaryData = [{
  years_at_school: 6,
  department: "Mathematics",
  e_id: "8"
}];

// Be careful with spread operator over objects.. it lacks of browser support yet! ..but works fine on latest Chrome version for example (69.0)
const finalData = mainData.map((person, index) => ({ ...person, data: secondaryData[index] }));

答案 3 :(得分:0)

一种略有不同的方法,只是使用带有循环的vanilla js map来匹配员工ID,并将第二个数组中的数据添加到第一个数组中的匹配对象中。我的猜测是,@MarkMeyer的答案可能会更快。

let arr1 = [{
  "name": "paul",
  "employee_id": "8"
}]

let arr2 = [{
  "years_at_school": 6, "department": "Mathematics",
  "e_id": "8"
}]

let results = arr1.map(obj1 => {
  for (let obj2 of arr2) {
    if (obj2.e_id === obj1.employee_id) {
      obj1.data = obj2;
      break;
    }
  }
  return obj1;
});

console.log(results);

答案 4 :(得分:0)

您的问题表明两个数组的大小始终相同。它还建议您将array2的内容放在data中具有相同索引的元素的字段array1中。如果这些假设是正确的,则:

// Array that will receive the extra data
const teachers = [
    { name: "Paul", employee_id: 8 },
    { name: "Mariah", employee_id: 10 }
];

// Array with the additional data
const extraData = [
    { years_at_school: 6, department: "Mathematics", e_id: 8 },
    { years_at_school: 8, department: "Biology", e_id: 10 },
];

// Array.map will iterate through all indices, and gives both the
const merged = teachers.map((teacher, index) => Object.assign({ data: extraData[index] }, teacher));

但是,如果要将数据添加到两个数组中且具有“ id”匹配的员工,则需要执行以下操作:

// Create a function to obtain the employee from an ID
const findEmployee = id => extraData.filter(entry => entry.e_id == id);

merged = teachers.map(teacher => {
    const employeeData = findEmployee(teacher.employee_id);

    if (employeeData.length === 0) {
        // Employee not found
        throw new Error("Data inconsistency");
    }

    if (employeeData.length > 1) {
        // More than one employee found
        throw new Error("Data inconsistency");
    }

    return Object.assign({ data: employeeData[0] }, teacher);
});