简体   繁体   English

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

[英]Merge objects with corresponding key values from two different arrays of objects

I've got two arrays that have multiple objects 我有两个有多个对象的数组

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

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

How can I achieve the following with either ES6 or Lodash? 如何使用ES6或Lodash实现以下目标?

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

I can merge but I'm not sure how to create a new child object and merge that in. 我可以合并,但我不知道如何创建一个新的子对象并将其合并。

Code I've tried: 代码我尝试过:

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

This merges to a top level array like so (which is not what I want): 这样就合并到一个顶级数组(这不是我想要的):

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

The connector between these two is "employee_id" and "e_id" . 这两者之间的连接器是"employee_id""e_id"

It's imperative that it's taken into account that they could be 1000 objects in each array, and that the only way to match these objects up is by "employee_id" and "e_id" . 必须考虑到每个阵列中可能有1000个对象,并且匹配这些对象的唯一方法是"employee_id""e_id"

In order to match up employee_id and e_id you should iterate through the first array and create an object keyed to employee_id . 为了匹配employee_ide_id您应该遍历第一个数组并创建一个键入employee_id的对象。 Then you can iterate though the second array and add the data to the particular id in question. 然后,您可以迭代第二个数组并将数据添加到相关的特定ID。 Here's an example with an extra item added to each array: 这是一个添加到每个数组的额外项目的示例:

 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) 

If you perform two nested O(n) loops (map+find), you'll end up with O(n^2) performance. 如果你执行两个嵌套的O(n)循环(map + find),你最终会得到O(n ^ 2)的性能。 A typical alternative is to create intermediate indexed structures so the whole thing is O(n). 一个典型的替代方案是创建中间索引结构,因此整个事物是O(n)。 A functional approach with lodash: 使用lodash的功能方法:

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

Hope this help you: 希望这能帮到你:

 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; }); 

Sorry, I've also fixed a missing coma in the second object and changed some other stuff. 对不起,我还修复了第二个对象中丢失的昏迷并改变了其他一些东西。

With latest Ecmascript versions: 随着最新的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] })); 

A slightly different approach just using vanilla js map with a loop to match the employee ids and add the data from the second array to the matching object from the first array. 稍微不同的方法是使用带有循环的vanilla js map来匹配employee ID,并将第二个数组中的数据添加到第一个数组中的匹配对象。 My guess is that the answer from @MarkMeyer is probably faster. 我的猜测是来自@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); 

Your question suggests that both arrays will always have the same size. 您的问题表明两个阵列总是具有相同的大小。 It also suggests that you want to put the contents of array2 within the field data of the elements with the same index in array1 . 它还建议您将array2的内容放在array1具有相同索引的元素的字段data中。 If those assumptions are correct, then: 如果这些假设是正确的,那么:

// 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));

However, if you want the data to be added to the employee with an "id" matching in both arrays, you need to do the following: 但是,如果要将数据添加到两个阵列中具有“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);
});

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

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