Объединение объектов с соответствующими значениями ключей из двух разных массивов объектов - PullRequest
0 голосов
/ 29 сентября 2018

У меня есть два массива, которые имеют несколько объектов

[
     {
         "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}))
})

Это сливается с массивом верхнего уровня, как это так (а это не то, что яwant):

{
     "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 голосов
/ 29 сентября 2018

Если вы выполните два вложенных цикла 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)}));
0 голосов
/ 29 сентября 2018

Ваш вопрос говорит о том, что оба массива всегда будут иметь одинаковый размер.Также предлагается, что вы хотите поместить содержимое 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);
});
0 голосов
/ 29 сентября 2018

Надеюсь, это поможет вам:

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] }));
0 голосов
/ 29 сентября 2018

Немного другой подход, использующий vanilla js map с циклом для сопоставления идентификаторов сотрудников и добавления данных из второго массива в соответствующий объект из первого массива.Я думаю, что ответ от @ 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);
0 голосов
/ 29 сентября 2018

Чтобы сопоставить employee_id и e_id, вам нужно пройтись по первому массиву и создать объект с ключом employee_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)
...