Home > Net >  Merge Javascript Objects WITH Same Key AND Include Duplicate Values WHERE Key Matches
Merge Javascript Objects WITH Same Key AND Include Duplicate Values WHERE Key Matches

Time:10-13

I am trying to merge some JSON data sets BY key value WHILE including duplicate values WHERE the key matches.

I have tried this quite a bit now but can't seem to produce the object that I need.

Object 1

[
  {"userId":"1",
   "email":"[email protected]"
  },
  {"userId":"2",
   "email":"[email protected]"
  }
]

Object 2

[
  {"id":"1abc",
   "listingId":"4def",
   "userId":"2"
  },
  {"id":"2abc",
   "listingId":"2def",
   "userId":"1"
  },
  {"id":"3abc",
   "listingId":"3def",
   "userId":"2"
  }
]

I need to merge these objects in a way that looks like this:

Desired Output

[
  {"id":"1abc",
   "listingId":"4def",
   "userId":"2",
   "email":"[email protected]"
  },
  {"id":"2abc",
   "listingId":"2def",
   "userId":"1",
   "email":"[email protected]"
  },
  {"id":"3abc",
   "listingId":"3def",
   "userId":"2",
   "email":"[email protected]"
  }
]


Problems I am Experiencing

I am able to merge the data sets successfully using a function that looks like this:

function merge(a, b, key) {

    function x(a) {
        a.forEach(function (b) {
            if (!(b[key] in obj)) {
                obj[b[key]] = obj[b[key]] || {};
                array.push(obj[b[key]]);
            }
            Object.keys(b).forEach(function (k) {
                obj[b[key]][k] = b[k];
            });
        });
    }

    var array = [],
        obj = {};

    x(a);
    x(b);
    return array;
}

https://stackoverflow.com/a/35094948/1951144

But it produces results that look like this:

[
  {"id":"1abc",
   "listingId":"4def",
   "userId":"2",
   "email":"[email protected]"
  },
  {"id":"2abc",
   "listingId":"2def",
   "userId":"1",
   "email":"[email protected]"
  }
]


Is there a way to use the above function WHILE keeping AND including the duplicate values where my keys match?

CodePudding user response:

For each element in arr2, create a new element containing the props of the item from arr2, and the email of the corresponding entry in arr1.

let arr1 = [
  {"userId":"1",
   "email":"[email protected]"
  },
  {"userId":"2",
   "email":"[email protected]"
  }
];

let arr2 = [
  {"id":"1abc",
   "listingId":"4def",
   "userId":"2"
  },
  {"id":"2abc",
   "listingId":"2def",
   "userId":"1"
  },
  {"id":"3abc",
   "listingId":"3def",
   "userId":"2"
  }
];

let output = arr2.map(a2 => ({...a2, email: arr1.find(a1 => a1.userId === a2.userId)?.email}));
console.log(output);

CodePudding user response:

This solution works even if the key isn't known yet. .flatMap() both arrays and pass in the desired key (in example it's "userId"). Use Object.entries() on each object so they will be an array of pairs.

[{A1: A1v}, {A2: A2v},...]
// into
[[A1, A1v], [A2, A2v],...]

.flatMap() the second array and on each iteration .flatMap() the first array. Then compare the given key ("userID") with the key of each object from the second array ("a") AND the value of that key and the value of the key of the object in the first array.

a === key && av === bv 

If both criteria are meet then merge those objects and return it, otherwise...

? {...objA, ...objB} 

return an empty array, which ultimately results to nothing since .flatMap() flattens one level of arrays.

: []

const arrA=[{userId:"1",email:"[email protected]"},{userId:"2",email:"[email protected]"}];const arrB=[{id:"1abc",listingId:"4def",userId:"2"},{id:"2abc",listingId:"2def",userId:"1"},{id:"3abc",listingId:"3def",userId:"2"}];

function masterKey(primary, key, secondary) { 
  let result = secondary.flatMap(objB => Object.entries(objB).flatMap(([b, bv]) =>   
    primary.flatMap(objA => Object.entries(objA).flatMap(([a, av]) =>
      a === key && av === bv ? {...objA, ...objB} : []))));
  return result;
}

console.log(masterKey(arrA, "userId", arrB));

  • Related