Merge property from an array of objects into anoth

2020-02-05 12:06发布

问题:

I have 2 arrays of objects, they each have an id in common. I need a property from objects of array 2 added to objects array 1, if they have matching ids.

Array 1:

[
    {
        id: 1,
        name: tom,
        age: 24
    },
    {
        id: 2,
        name: tim,
        age: 25
    },
    {
        id: 3,
        name: jack,
        age: 24
    },

]

Array 2:

[
    {
        id: 1,
        gender: male,
        eyeColour: blue,
        weight: 150
    },
    {
        id: 2,
        gender: male,
        eyeColour: green,
        weight: 175
    },
    {
        id: 3,
        gender: male,
        eyeColour: hazel,
        weight: 200
    },

]

Desired Outcome:

[
    {
        id: 1,
        name: tom,
        age: 24,
        eyeColour: blue,
    },
    {
        id: 2,
        name: tim,
        age: 25,
        eyeColour: green,
    },
    {
        id: 3,
        name: jack,
        age: 24,
        eyeColour: hazel,
    },

]

I tried using lodash _.merge function but then I end up with all properties into one array, when I only want eyeColour added.

回答1:

Just noticed Paul answered while I was working on my answer but I'll add my very similar code anyway:

var getEyeColour = function (el) { return _.pick(el, 'eyeColour'); }
var out = _.merge(arr1, _.map(arr2, getEyeColour));

DEMO



回答2:

Lodash remains a highly useful bag of utilities, but with the advent of ES6 some of its use cases are less compelling.

For each object (person) in the first array, find the object in the second array with matching ID (see function findPerson). Then merge the two.

function update(array1, array2) {
  var findPerson = id => array2.find(person => person.id === id);

  array1.forEach(person => Object.assign(person, findPerson(person.id));
}

For non-ES6 environments, rewrite arrow functions using traditional syntax. If Array#find is not available, write your own or use some equivalent. For Object.assign, if you prefer use your own equivalent such as _.extend.

This will merge all properties from array2 into array1. To only merge eyeColour:

function update(array1, array2) {
  var findPerson = id => array2.find(person => person.id === id);

  array1.forEach(person => {
    var person2 = findPerson(person.id));
    var {eyeColour} = person2;
    Object.assign(person, {eyeColour});
  });
}


回答3:

You can use pick to get only the properties you want before merging:

var result = _.merge( arr1, _.map( arr2, function( obj ) {
    return _.pick( obj, 'id', 'eyeColour' );
}));


回答4:

A solution in plain Javascript

This is a more generic solution for merging two arrays which have different properties to union in one object with a common key and some properties to add.

var array1 = [{ id: 1, name: 'tom', age: 24 }, { id: 2, name: 'tim', age: 25 }, { id: 3, name: 'jack', age: 24 }, ],
    array2 = [{ id: 1, gender: 'male', eyeColour: 'blue', weight: 150 }, { id: 2, gender: 'male', eyeColour: 'green', weight: 175 }, { id: 3, gender: 'male', eyeColour: 'hazel', weight: 200 }, ];

function merge(a, b, id, keys) {
    var array = [], object = {};

    function m(c) {
        if (!object[c[id]]) {
            object[c[id]] = {};
            object[c[id]][id] = c[id];
            array.push(object[c[id]]);
        }
        keys.forEach(function (k) {
            if (k in c) {
                object[c[id]][k] = c[k];
            }
        });
    }
    a.forEach(m);
    b.forEach(m);
    return array;
}

document.write('<pre>' + JSON.stringify(merge(array1, array2, 'id', ['name', 'age', 'eyeColour']), 0, 4) + '</pre>');