Home > Software engineering >  Merge objects with same id in array in js
Merge objects with same id in array in js

Time:06-09

I guess have a dead simple problem but still didn't find a solution I have an array which looks like this:

var originalArray = [
{
  pid: 1,
  coordinates: {x: "50", y: null, f: null}
},
{
  pid: 1,
  coordinates: {x: null, y: "22", f: null}
},
{
  pid: 1,
  coordinates: {x: null, y: null, f: "2"}
},
{
  pid: 2,
  coordinates: {x: "23", y: null, f: null}
},
{
  pid: 2,
  coordinates: {x: null, y: "62", f: null}
},
{
  pid: 2,
  coordinates: {x: null, y: null, f: "15"}
}
]

I'd like to modify it to look like this (merge by id and join elements):

var originalArray = [
{
  pid: 1,
  coordinates: {x: "50", y: "22", f: "2"}
},
{
  pid: 2,
  coordinates: {x: "23", y: "62", f: "15"}
}
]

I already had multiple tries but still didn't find an elegant way of doing it.

CodePudding user response:

You can group the array by pids and merge the non null coordinates using reduce.

const originalArray = [
  { pid: 1, coordinates: { x: "50", y: null, f: null } },
  { pid: 1, coordinates: { x: null, y: "22", f: null } },
  { pid: 1, coordinates: { x: null, y: null, f: "2" } },
  { pid: 2, coordinates: { x: "23", y: null, f: null } },
  { pid: 2, coordinates: { x: null, y: "62", f: null } },
  { pid: 2, coordinates: { x: null, y: null, f: "15" } },
];

const result = Object.values(
  originalArray.reduce((r, o) => {
    r[o.pid] ??= { pid: o.pid };
    r[o.pid].coordinates = {
      ...r[o.pid].coordinates,
      ...Object.entries(o.coordinates).reduce(
        (r, [k, v]) => (v && (r[k] = v), r),
        {}
      ),
    };
    return r;
  }, {})
);

console.log(result);

Relevant Documentations:

CodePudding user response:

const input = [
  { pid: 1, coordinates: { x: "50", y: null, f: null } },
  { pid: 1, coordinates: { x: null, y: "22", f: null } },
  { pid: 1, coordinates: { x: null, y: null, f: "2" } },
  { pid: 2, coordinates: { x: "23", y: null, f: null } },
  { pid: 2, coordinates: { x: null, y: "62", f: null } },
  { pid: 2, coordinates: { x: null, y: null, f: "15" } },
];

const mergeByIdWhereEntry = (array, id, entries, predicate) => Array.from(
  array.reduce(
    (entriesById, { [id]: key, [entries]: value }) => entriesById.set(
      key,
      Object.assign(
        entriesById.get(key) ?? {},
        Object.fromEntries(
          Object.entries(value).filter(predicate),
        ),
      ),
    ),
    new Map(),
  ),
  ([key, value]) => ({ [id]: key, [entries]: value }),
);

const output = mergeByIdWhereEntry(input, 'pid', 'coordinates', (entry) => entry[1]);

console.log(output);

Here's one way to merge by an id and join the elements. It reduces the array into a Map of each merged coordinates by pid, then converts the map back into an array of the object in the original form.

  • Related