1

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.

2
  • These are not associative arrays. They are arrays of objects. The term "associative array" is not used in JS. Commented Jan 14, 2016 at 17:01
  • Removed that term, any idea how to solve the problem? Commented Jan 14, 2016 at 17:05

5 Answers 5

7

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});
  });
}
Sign up to request clarification or add additional context in comments.

Comments

2

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 Comments

Am I missing something, or does this solution assume that the order of the elements in the two arrays are the same?
Yes, and that's a mistake. OP you should probably ignore this.
1

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

2 Comments

@Andy Thanks for fixing that.
Not quite sure about this. What is the point of picking id? It will overwrite a (possibly different) id in the first array.
1

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

1 Comment

Personal super hero :-)
0

I was looking for the same, but I want to match Id before merging

And in my case, second array may have different number of items, finally I came with this:

var out = arr1.map(x => {
    return  { ...x, eyeColour:  arr2.find(y => x.id === y.id)?.eyeColour }
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.