3

I want to merge 2 object with same key, value from 2 array, something like this:

var arr1 = [
    { a: "a", 1: 1, 2: 2 },
    { a: "b", 1: 1, 2: 3 }
];

var arr2 = [
    { a: "a", 3: 123 },
    { a: "b", 3: 4411 }
];

var arr3 = _.map(arr1, function(a1) {
    var a3 = {};

    _.map(arr2, function(a2) {
        if (a1.a == a2.a) {
            a3 = _.extend(a1, a2);
        }
    })

    return a3
});

result:

arr3 = [ 
  { '1': 1, '2': 2, '3': 123, a: 'a' },
  { '1': 1, '2': 3, '3': 4411, a: 'b' } 
]

Does it look stupid? Are there any others ways to do this? Thanks for reading.

Bee
  • 41
  • 1
  • 2
  • 1
    is your solution working or not?What is the question? – brk Sep 23 '17 at 06:14
  • it worked, but i think there are some other better ways to do that with some library. (im not tested with big array length yet) – Bee Sep 23 '17 at 06:17
  • While posting question please be more specific. For example mention which JavaScript library you are used. It will help people to investigate on the similar kind of library your are used. – Vijayanath Viswanathan Sep 23 '17 at 06:40
  • what means same key? same index or same key `a`? – Nina Scholz Sep 23 '17 at 07:30
  • Possible duplicate of [How to use Lodash to merge two collections based on a key?](https://stackoverflow.com/questions/35091975/how-to-use-lodash-to-merge-two-collections-based-on-a-key) – Gruff Bunny Sep 23 '17 at 08:07

2 Answers2

8

Use a lodash chain to concat the arrays, group similar objects, and then merge each group to a single object:

var arr1 = [{ a: "a", 1: 1, 2: 2 }, { a: "b", 1: 1, 2: 3 }];
var arr2 = [{ a: "a", 3: 123 }, { a: "b", 3: 4411 }];

var result = _(arr1)
  .concat(arr2) // concat the 2nd array
  .groupBy('a') // group by the identical key
  .map(_.spread(_.curry(_.merge, {}))) // left currey merge to to create a new empty object, and spread the group as parameters
  .value();
  
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

With ES6 you can use Array#reduce to collect the similar objects in a Map, then get the Map#values iterator, and use the spread syntax to convert to an array:

const arr1 = [{ a: "a", 1: 1, 2: 2 }, { a: "b", 1: 1, 2: 3 }];
const arr2 = [{ a: "a", 3: 123 }, { a: "b", 3: 4411 }];

const result = [...arr1.concat(arr2) // concat the arrays
  .reduce((m, o) => m.set(o.a, Object.assign(m.get(o.a) || {}, o)), // use a map to collect similar objects
  new Map()
).values()]; // get the values iterator of the map, and spread into a new array
  
console.log(result);
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
  • Lodash way is working. ES6 version is not working though. – Ajinkya Nov 28 '17 at 12:28
  • @Ajinkya - have you tried running the snippets? If so, what browser are you using? – Ori Drori Nov 28 '17 at 12:35
  • My bad. I did not replace property 'a' for es6 snippet. Both the snippets are working. Which one do you recommend to use considering the performance? – Ajinkya Nov 28 '17 at 14:29
  • 2
    @Ajinkya - I don't really know to tell you the truth. If the amount of items is small, it doesn't really matter. If the amount is huge, you should with lodash, since spread is not stack safe. You'll need to profile it. – Ori Drori Nov 28 '17 at 14:32
4

you can do

var arr1 = [
    { a: "a", 1: 1, 2: 2 },
    { a: "b", 1: 1, 2: 3 }
];

var arr2 = [
    { a: "a", 3: 123 },
    { a: "b", 3: 4411 }
];

let result = arr1.map((e) => {
    for(let element of arr2){
        if(e.a == element.a) Object.assign(e, element);
    }
    return e;
});
console.log(result);
marvel308
  • 10,288
  • 1
  • 21
  • 32