1

I have two object arrays like -

var arrayOne = [{"Content":1, "ValueContent":2},{"Content":3, "ValueContent":4}]
var arrayTwo = [{"Ex": "x", "ValueNum":20,"Content_Key":3}, {"Ex":"y","ValueNum":10,"Content_Key": 1}]

I want to match Content value from arrayOne to Content_Key value in arrayTwo. If its a match the update arrayTwo with ValueContent from arrayOne. So the updated array would look like -

 var arrayTwo = [{"Ex": "x", "ValueNum":20,"Content_Key":3, "ValueContent":4}, {"Ex":"y","ValueNum":10,"Content_Key": 1, "ValueContent":2}]

Any leads on how to do this? Currently i am able to the matching part but beyond that am stuck.

skypjack
  • 49,335
  • 19
  • 95
  • 187
KBM
  • 341
  • 4
  • 16

5 Answers5

4

Performance is optimised if you use some kind of hash for this. As others have shown you can create an object for this, but here is a solution with an ES6 Map, which is passed as the thisArg to forEach:

arrayTwo.forEach(function (el) {
    el.ValueContent = this.get(el.Content_Key);
}, new Map(arrayOne.map(el => [el.Content, el.ValueContent])));

var arrayOne = [{"Content":1, "ValueContent":2},{"Content":3, "ValueContent":4}];
var arrayTwo = [{"Ex": "x", "ValueNum":20,"Content_Key":3}, {"Ex":"y","ValueNum":10,"Content_Key": 1}];

arrayTwo.forEach(function (el) {
    el.ValueContent = this.get(el.Content_Key);
}, new Map(arrayOne.map(el => [el.Content, el.ValueContent])));

console.log(arrayTwo);

Remark

You use property names that have the first character capitalised. You might want to consider starting with a lowercase letter for these, as there is a convention to reserve the initial uppercases for names of constructors (or classes in ES6).

Community
  • 1
  • 1
trincot
  • 317,000
  • 35
  • 244
  • 286
  • I thought that convention is for variables, not properties of plain objects. It would make objects a lot less useful otherwise, since often times you don't exactly know what data would go in them as it might be coming in from JSON or maybe user input or something. – VLAZ Oct 01 '16 at 09:22
  • @vlas, properties can also be constructors, so it would make sense to apply the convention throughout. You'll notice that the syntax highlighter of StackOverflow also applies a different color for such properties. Of course, if you have constraints in your source data, then you should just ignore this convention ;-) – trincot Oct 01 '16 at 10:13
0

You could use a hash table for arrayOne and apply ValueContent to the appropriate object if exist.

var arrayOne = [{ "Content": 1, "ValueContent": 2 }, { "Content": 3, "ValueContent": 4 }],
    arrayTwo = [{ "Ex": "x", "ValueNum": 20, "Content_Key": 3 }, { "Ex": "y", "ValueNum": 10, "Content_Key": 1 }],
    hash = Object.create(null);

arrayOne.forEach(function (a) {
    hash[a.Content] = a;
});

arrayTwo.forEach(function (a) {
    if (hash[a.Content_Key]) {
        a.ValueContent = hash[a.Content_Key].ValueContent;
    }
});

console.log(arrayTwo);    
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

First I would create an index of objects within arrayTwo where the key would be the Content_Key. That is, I would build an object where properties are Content_Key and values the objects within the whole array.

Thus, I can locate objects by Content_Key easily.

Finally, I would iterate each item in arrayOne to add ValueContent property to them using the whole object index:

var arrayOne = [{"Content":1, "ValueContent":2},{"Content":3, "ValueContent":4}];
var arrayTwo = [{"Ex": "x", "ValueNum":20,"Content_Key":3}, {"Ex":"y","ValueNum":10,"Content_Key": 1}];

var arrayTwoIndex = arrayTwo.reduce(function(result, item) {
  result[item.Content_Key] = item;
  
  return result;
}, {});

arrayOne.forEach(function(item) {
   // This approach of using an object index is very powerful because
   // otherwise you would need to iterate arrayTwo for each arrayOne
   // iteration, and this way you save a lot of CPU cycles because 
   // you're directly accessing to arrayTwo objects by Content_Key!
   arrayTwoIndex[item.Content].ValueContent = item.ValueContent;
});

console.log(JSON.stringify(arrayTwo));
Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
0

Try this simple approach (reduces the complexity to O(n+m) where n is number of items in arrayOne and m is number of items in arrayTwo)

var arrayOne = [{"Content":1, "ValueContent":2},{"Content":3, "ValueContent":4}];
var arrayTwo = [{"Ex": "x", "ValueNum":20,"Content_Key":3}, {"Ex":"y","ValueNum":10,"Content_Key": 1}];

//prepare map from arrayone for Content value
var map = {};
arrayOne.forEach( function( item ){
  map[ item[ "Content" ] ] = item[ "ValueContent" ];
});

//Now iterate arrayTwo to see if there is a match
arrayTwo = arrayTwo.map( function( item ){
  var contentKey = item[ "Content_Key" ];
  if ( map[ contentKey ] != undefined )
  {
      item[ "ValueContent" ] = map[ contentKey ];
  }
  return item;
});

console.log( arrayTwo );
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
0

You can use 2 forEach methods

arrayTwo.forEach(obj2 => { arrayOne.forEach(obj1 => {
if (obj2.Content_Key === obj1.Content)  obj2.ValueContent = obj1.ValueContent;
})});
console.log(arrayTwo); //[ { Ex: 'x', ValueNum: 20, Content_Key: 3, ValueContent: 4 }, { Ex: 'y', ValueNum: 10, Content_Key: 1, ValueContent: 2 } ]
kevin ternet
  • 4,514
  • 2
  • 19
  • 27