1

I've looked through every "Merge JSON Objects on Same Key" question in SO, but to no avail.

I have two arrays of different-length JSON objects, like so, and I need to merge each JSON object that has a shared key (in this case, realName) and dump what is not appearing in both:

  let arrObjA = [{
    "index": 114,
    "realName": 'kevin',
    "bucket": 'boss',
    "react_name": 'BossKevin'
  },
  {
    "index": 115,
    "realName": 'angela',
    "bucket": 'boss',
    "react_name": 'BossAngela'
  },
  {
    "index": 116,
    "realName": 'james',
    "bucket": 'janitor',
    "react_name": 'JanitorJames'
  },
  {
    "index": 117,
    "realName": 'arthur',
    "bucket": 'employee',
    "react_name": 'EmployeeArthur'
  }
]

And

let arrObjB = [{
        "boxName": "building",
        "realName": "angela",
        "boxValue": "2"
      },
      {
        "boxName": "building",
        "realName": "james",
        "boxValue": "false"
      },
      {
        "boxName": "building",
        "realName": "arthur",
        "boxValue": "0"
      },
      ]

The result should be:

let result = [{
    "index": 115,
    "realName": 'angela',
    "bucket": 'boss',
    "react_name": 'BossAngela',
    "boxName": "building",
    "boxValue": "2"
  },
  {
    "index": 116,
    "realName": 'james',
    "bucket": 'janitor',
    "react_name": 'JanitorJames',
    "boxName": "building",
    "boxValue": "false"
  },
  {
    "index": 117,
    "realName": 'arthur',
    "bucket": 'employee',
    "react_name": 'EmployeeArthur',
    "boxName": "building",
    "boxValue": "0"
  }
]

So the new JSON objects in the new array (result) are merged JSON object where the key realName is shared between the original JSON objects (e.g., arrObjA["realName"] === arrObjB["realName"]). And the one JSON object with the realName "kevin" from arrObjA is not in the new array since it that key/value does not appear in a JSON object in both arrays.

I have tried the following from another SO answer, which has brought me closest to the result I need (out of all the other few dozen answers that I've tried), but I only get a single key/value because I don't know how to expand the objects.

const mappingEngine = (arrA, arrB) => {
  const resultsKeys = ["realName", "bucket"];

  const result = arrA
    .filter(function (o1) {
      return arrB.some(function (o2) {
        return o1.realName === o2.realName; // assumes unique id
      });
    })
    .map(function (o) {
      console.log(o)
      return resultsKeys.reduce(function (newo, name) {
        newo[name] = o[name];
        return newo;
      }, {});
    });
  return result;
};

Thank you for any help.

RichardS
  • 135
  • 1
  • 9

2 Answers2

5

You can use es6 spread (...) operator to marge two objects.

let arrObjA = [{ "index": 114, "realName": 'kevin', "bucket": 'boss', "react_name": 'BossKevin' }, { "index": 115, "realName": 'angela', "bucket": 'boss', "react_name": 'BossAngela' }, { "index": 116, "realName": 'james', "bucket": 'janitor', "react_name": 'JanitorJames' }, { "index": 117, "realName": 'arthur', "bucket": 'employee', "react_name": 'EmployeeArthur' }]
let arrObjB = [{ "boxName": "building", "realName": "angela", "boxValue": "2" }, { "boxName": "building", "realName": "james", "boxValue": "false" }, { "boxName": "building", "realName": "arthur", "boxValue": "0" },]

let result = arrObjB.map(item => ({
    ...arrObjA.find(({ realName }) => item.realName == realName),
    ...item,
}));

console.log(result)
Nur
  • 2,361
  • 2
  • 16
  • 34
0

I have a different approach for your problem . I don't use reduce . I map the first array and inside the mapping filter the first element from the second array that match with the actual element mapped . Here how I did it with code :

let arrObjA = [{
    "index": 114,
    "realName": 'kevin',
    "bucket": 'boss',
    "react_name": 'BossKevin'
  },
  {
    "index": 115,
    "realName": 'angela',
    "bucket": 'boss',
    "react_name": 'BossAngela'
  },
  {
    "index": 116,
    "realName": 'james',
    "bucket": 'janitor',
    "react_name": 'JanitorJames'
  },
  {
    "index": 117,
    "realName": 'arthur',
    "bucket": 'employee',
    "react_name": 'EmployeeArthur'
  }
];

let arrObjB = [{
    "boxName": "building",
    "realName": "angela",
    "boxValue": "2"
  },
  {
    "boxName": "building",
    "realName": "james",
    "boxValue": "false"
  },
  {
    "boxName": "building",
    "realName": "arthur",
    "boxValue": "0"
  },
];

const mappingEngine = (arrA, arrB) => {
  const a_key = "realName";
  const b_key = "realName";

  const result = arrA
    .map(function(o) {
      let b = arrB.filter(n_b => o[a_key] == n_b[b_key]);
      //Take the first element that is compatible
      if (b == null) {
        return {
          o
        };
      } else {
        let c = b[0];
        return { ...o,
          ...c
        };
      }
    });
  console.log(result);
  return result;
};

mappingEngine(arrObjA,arrObjB);

Please use filter to remove the keys that are on arrA but not on arrB . I just do a left join from arrA to arrB . It is like : SELECT * FROM arrA LEFT JOIN arrB;

thecassion
  • 506
  • 1
  • 7
  • 19