muthu
muthu

Reputation: 803

How to merge specific key to the another object with respect to common key?

I have an array which have many records. Need to merge objects based on a condition(not applicable to all the object available inside an array), In this case first need to compare the data with name.
step 1: Need to find objects in array which have similar name.
step 2: If we have same data, next compare the status key among the matched data.
step 3:
case1: If any one of the object among the matched data has status as true(set status: true) then need to merge all the likings key to that object. case2: If all the object among the matched data has status as false then(set status: false) need to merge all the likings key to any of the object.
How to achieve this?

Array

[
  {
    name: 'jane',
    age: 10,
    status: true,
    likings: [{ sports: 'football', books: 'harrypotter' }],
  },
  {
    name: 'sam',
    age: 20,
    status: false,
    likings: [{ sports: 'basketball', books: 'book1' }],
  },
  {
    name: 'jane',
    age: 10,
    status: false,
    likings: [{ sports: 'chess', books: 'book2' }],
  },
  {
    name: 'robert',
    age: 40,
    status: false,
    likings: [{ sports: 'carrom', books: 'book3' }],
  },
  {
    name: 'jane',
    age: 10,
    status: false,
    likings: [{ sports: 'gaming', books: 'book4' }],
  },
];


Expected o/p

[
  {
    name: 'jane',
    age: 10,
    status: true,
    likings: [
      { sports: 'football', books: 'harrypotter' },
      { sports: 'gaming', books: 'book4' },
      { sports: 'chess', books: 'book2' },
    ],
  },
  {
    name: 'sam',
    age: 20,
    status: false,
    likings: [{ sports: 'basketball', books: 'book1' }],
  },
  {
    name: 'robert',
    age: 40,
    status: false,
    likings: [{ sports: 'carrom', books: 'book3' }],
  },
];

Upvotes: 1

Views: 442

Answers (2)

shotasenga
shotasenga

Reputation: 979

I don't think I fully understood your requirement especially about "similar name". So I assume that you want to group the records based on the "name" and all the records which have the same "name" will have the same "age".

The solution below is grouping the records using an object hash and keep concatenating the likings into the element. After finishing it, return the all elements of the object by calling Object.values() which should maintain the order of appearance of names.

Is this something you want, or at least give you some idea? Hope it helps.

function merge(records) {
  const hash = {};

  for (let i = 0; i < records.length; i++) {
    const element = records[i];
    const key = element.name; // if you want to do something for "similarity", do something here.

    hash[key] = {
      ...element,
      status: (hash[key] && hash[key].status) || element.status,
      likings: element.likings.concat((hash[key] && hash[key].likings) || []),
    };
  }

  return Object.values(hash);
}

const data = [
  {
    name: "jane",
    age: 10,
    status: true,
    likings: [{ sports: "football", books: "harrypotter" }],
  },
  {
    name: "sam",
    age: 20,
    status: false,
    likings: [{ sports: "basketball", books: "book1" }],
  },
  {
    name: "jane",
    age: 10,
    status: false,
    likings: [{ sports: "chess", books: "book2" }],
  },
  {
    name: "robert",
    age: 40,
    status: false,
    likings: [{ sports: "carrom", books: "book3" }],
  },
  {
    name: "jane",
    age: 10,
    status: false,
    likings: [{ sports: "gaming", books: "book4" }],
  },
];

console.log(merge(data));

Upvotes: 1

Nick Parsons
Nick Parsons

Reputation: 50874

You can use .reduce() to merge all objects with the same name into a Map. This can by keeping a map of keys of name, and values of objects with that name. Whenever you encounter a new object in your array, you can check if it exists in the map. If it does, you can add to the likings array stored in the associated object. You can also update the status to true if the current object is true. If the object's name doesn't exist in the map as a key, you can add the object as a value, which further subsequent iterations of reduce can merge into.

See example below:

const arr = [ { name: 'jane', age: 10, status: true, likings: [{ sports: 'football', books: 'harrypotter' }], }, { name: 'sam', age: 20, status: false, likings: [{ sports: 'basketball', books: 'book1' }], }, { name: 'jane', age: 10, status: false, likings: [{ sports: 'chess', books: 'book2' }], }, { name: 'robert', age: 40, status: false, likings: [{ sports: 'carrom', books: 'book3' }], }, { name: 'jane', age: 10, status: false, likings: [{ sports: 'gaming', books: 'book4' }], }, { name: 'sam', age: 10, status: false, likings: [{ sports: 'gaming', books: 'book5' }], }];

const merged = [...arr.reduce((m, o) => {
  const curr = m.get(o.name) || {};
  return m.set(o.name, {...o, status: curr.status || o.status, likings: [...(curr && curr.likings || []), ...o.likings]});
}, new Map).values()]

console.log(merged);

Upvotes: 1

Related Questions