使用匹配的对象键将JS对象数组推送到另一个对象数组

时间:2018-11-08 13:04:12

标签: javascript arrays javascript-objects

我想合并来自多个来源的一堆对象,因此我可以使用一个大对象,而不是说5个或10个对象。

假设我的主要对象数组包含员工要向其推送其他数组的基本数据,

var employees = [
{emp_id: 1, emp_name: "John D", phone:"123456"},
{emp_id: 2, emp_name: "Mary J", phone:"234567"},
{emp_id: 3, emp_name: "Doe J", phone:"345678"},
{emp_id: 4, emp_name: "Jane M", phone:"456789"}
]

另一个具有员工工作历史记录的对象数组:

var employee_history = [
{emp_id: 1, company: "ABC", Years: 4},
{emp_id: 2, company: "BCD", Years: 3},
{emp_id: 3, company: "CDE", Years: 2},
{emp_id: 4, company: "DEF", Years: 1}
]

最后一个对象数组,其中包含员工的居住历史记录:

var cities_lived = [
{emp_id: 1, city: "Moscow", Years: 1},
{emp_id: 1, city: "Doha", Years: 1},
{emp_id: 2, city: "Cairo", Years: 2},
{emp_id: 2, city: "London", Years: 1},
{emp_id: 3, city: "Tunis", Years: 2},
{emp_id: 3, city: "Beijing", Years: 2},
{emp_id: 4, city: "New York", Years: 1},
{emp_id: 4, city: "Capetown", Years: 1}
]

因此,我想使用employee_history属性将cities_livedemployees推入emp_id内部的各个对象中,以进行匹配并获得类似或类似结果的输出只要它在单个对象中:

[
{
emp_id: 1, 
emp_name: "John D", 
phone: "123456", 
company: "ABC", 
Years: 4, 
cities: [
    {emp_id: 1, city: "Doha", Years: "1"}, 
    {emp_id: 1, city: "Doha", Years: "1"}
] 
},
{},
{},
...
]

我该如何实现?

我麻烦的解决方案是循环每个对象数组并创建新对象,然后将数据推送到其中,然后将结果最终推送到主对象数组中。但是我不喜欢必须手动执行所有操作的想法,即使那样我也不确定如何将结果推送到emp_id属性匹配的主对象数组中。

3 个答案:

答案 0 :(得分:1)

您需要遍历城市和历史记录数组,并以emp_id作为键来创建地图。 并插入最终对象。

尝试

var employees = [
{emp_id: 1, emp_name: "John D", phone:"123456"},
{emp_id: 2, emp_name: "Mary J", phone:"234567"},
{emp_id: 3, emp_name: "Doe J", phone:"345678"},
{emp_id: 4, emp_name: "Jane M", phone:"456789"}
]


var employee_history = [
{emp_id: 1, company: "ABC", Years: 4},
{emp_id: 2, company: "BCD", Years: 3},
{emp_id: 3, company: "CDE", Years: 2},
{emp_id: 4, company: "DEF", Years: 1}
]

var cities_lived = [
{emp_id: 1, city: "Moscow", Years: 1},
{emp_id: 1, city: "Doha", Years: 1},
{emp_id: 2, city: "Cairo", Years: 2},
{emp_id: 2, city: "London", Years: 1},
{emp_id: 3, city: "Tunis", Years: 2},
{emp_id: 3, city: "Beijing", Years: 2},
{emp_id: 4, city: "New York", Years: 1},
{emp_id: 4, city: "Capetown", Years: 1}
]


var cities_lived_obj = cities_lived.reduce(function(o,i){
   if(!o.hasOwnProperty(i.emp_id)){
       o[i.emp_id] = [];
   }
   o[i.emp_id].push(i);
   return o;
},{});

var employee_history_obj = employee_history.reduce(function(o,i){

   if(!o.hasOwnProperty(i.emp_id)){
       o[i.emp_id] = [];
   }
   o[i.emp_id].push(i);
   return o;
},{});

employees.forEach(function(emp){
  emp['cities'] = cities_lived_obj[emp.emp_id];
  emp['history'] = employee_history_obj[emp.emp_id];
});

console.log(employees);

JsFiddle演示-https://jsfiddle.net/f3bh0eop/2/

答案 1 :(得分:1)

是的,这很容易做到。您只需要遍历员工并逐步构建对象,在循环结束时,您将获得所需的结果。

var employees = [
  { emp_id: 1, emp_name: "John D", phone: "123456" },
  { emp_id: 2, emp_name: "Mary J", phone: "234567" },
  { emp_id: 3, emp_name: "Doe J", phone: "345678" },
  { emp_id: 4, emp_name: "Jane M", phone: "456789" }
];


var employee_history = [
  { emp_id: 1, company: "ABC", Years: 4 },
  { emp_id: 2, company: "BCD", Years: 3 },
  { emp_id: 3, company: "CDE", Years: 2 },
  { emp_id: 4, company: "DEF", Years: 1 }
];

var cities_lived = [
  { emp_id: 1, city: "Moscow", Years: 1 },
  { emp_id: 1, city: "Doha", Years: 1 },
  { emp_id: 2, city: "Cairo", Years: 2 },
  { emp_id: 2, city: "London", Years: 1 },
  { emp_id: 3, city: "Tunis", Years: 2 },
  { emp_id: 3, city: "Beijing", Years: 2 },
  { emp_id: 4, city: "New York", Years: 1 },
  { emp_id: 4, city: "Capetown", Years: 1 }
];

employees.forEach(employee => {
  const employeeHistory = employee_history.find(x => x.emp_id == employee.emp_id);
  employee = { ...employee, ...employeeHistory };
  const employeeCities = cities_lived.filter(x => x.emp_id === employee.emp_id);
  employee.cities = [];

  if (employeeCities && employeeCities.length > 0) {
    employee.cities = employeeCities;
  }
});

答案 2 :(得分:1)

您可以尝试编写很少起作用的小功能,然后将它们组合为一个将项目合并为一个项目的函数。

然后将需要与它们的合并功能合并的所有数据,并将员工减少到可以合并所有内容的新值。

const employees = [{"emp_id":1,"emp_name":"John D","phone":"123456"},{"emp_id":2,"emp_name":"Mary J","phone":"234567"},{"emp_id":3,"emp_name":"Doe J","phone":"345678"},{"emp_id":4,"emp_name":"Jane M","phone":"456789"}];
const employee_history = [{"emp_id":1,"company":"ABC","Years":4},{"emp_id":2,"company":"BCD","Years":3},{"emp_id":3,"company":"CDE","Years":2},{"emp_id":4,"company":"DEF","Years":1}];
const cities_lived = [{"emp_id":1,"city":"Moscow","Years":1},{"emp_id":1,"city":"Doha","Years":1},{"emp_id":2,"city":"Cairo","Years":2},{"emp_id":2,"city":"London","Years":1},{"emp_id":3,"city":"Tunis","Years":2},{"emp_id":3,"city":"Beijing","Years":2},{"emp_id":4,"city":"New York","Years":1},{"emp_id":4,"city":"Capetown","Years":1}];
const whatever = [{ emp_id: 1, whatever: 'whatever' }];//extra to merge item

//merges items with the merger function from toMerge array in uniqueArray 
//  if they match using matcher 
const mergeIn = (uniqueArray, toMerge, matcher, merger) =>
  uniqueArray.map((item) =>
    merger(item, toMerge.filter(matcher(item))),
  );
//create a merger function set item[itemFieldName] with a mapped result 
//  of others using mapper function
const merger = (itemFieldName, mapper) => (
  item,
  others,
) => ({
  ...item,
  [itemFieldName]: others.map(mapper),
});
//match on emp_id
const matchEpmId = (item) => (other) =>
  item.emp_id === other.emp_id;

console.log(
  [
    [
      cities_lived,
      //merger function that sets item.cities with others mapped to {city,Years}
      merger('cities', ({ city, Years }) => ({ city, Years}))
    ],
    [
      employee_history,
      //merger function that sets item.history with others mapped to {company,Years}
      merger('history', ({ company, Years }) => ({ company, Years}))
    ],
    [
      whatever,//extra to merge items
      merger('whatever', ({ whatever }) => whatever),
    ],
  ].reduce(
    (result, [other, merger]) =>
      mergeIn(result, other, matchEpmId, merger),
    employees,
  ),
);