Home > Software engineering >  How can i merge old and new objects in one array without creating an object inside object?
How can i merge old and new objects in one array without creating an object inside object?

Time:04-05

const array = [{
  "id": "1",
  "main": [{
    "type": "a",
    "nu": '0',
    "role": 1
  }],
}, {
  "id": "2",
  "main": [{
    "type": "b",
    "nu": '0',
    "role": 2
  }],
}, {
  "id": "3",
  "main": [{
    "type": "c",
    "nu": '0',
    "role": 2
  }],
}, {
  "id": "4",
  "main": [{
    "type": "d",
    "nu": '0',
    "role": 2
  }],
}]

From above object, i want to combine id- 2,3 and 4 into one key which has 3 objects.

const result = [array.reduce((acc, {id, main}) => {
  const { nu, role, type } = main[0]
  const hash = `${nu}-${role}`;
  acc[hash] = acc[hash] ? [{ ...acc[hash] }, {type: type, id: id }] : 
{ type, id: [id] };
  return acc;
}, {})];

Expected:

Example:

const array = [{
  "id": "1",
  "main": [{
    "type": "a",
    "nu": '0',
    "role": 1
  }],
}, {
  "id": "2",
  "main": [{
    "type": "b",
    "nu": '0',
    "role": 2
  }],
}, {
  "id": "3",
  "main": [{
    "type": "c",
    "nu": '0',
    "role": 2
  }],
}, {
  "id": "4",
  "main": [{
    "type": "d",
    "nu": '0',
    "role": 2
  }],
}]

const result = [array.reduce((acc, {id, main}) => {
  const { nu, role, type } = main[0]
  const hash = `${nu}-${role}`;
  acc[hash] = acc[hash] ? [{ ...acc[hash] }, {type: type, id: id }] : 
{ type, id: [id] };
  return acc;
}, {})];

console.log(result);

I am not sure where i am going wrong, can someone please help ?

CodePudding user response:

You could reduce the arrays with an object and a common key with padded zeroes at start.

const
    data = [{ id: "1", main: [{ type: "a", nu: "0", role: 1 }] }, { id: "2", main: [{ type: "b", nu: "0", role: 2 }] }, { id: "3", main: [{ type: "c", nu: "0", role: 2 }] }, { id: "4", main: [{ type: "d", nu: "0", role: 2 }] }],
    result = data.reduce((r, { id, main }) => {
        main.forEach(({ type, nu, role }) => {
            const key = `${nu.toString().padStart(3, 0)}-${role}`;
            (r[key] ??= []).push({ id, type });
        });
        return r;
    }, {});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

For getting an exact result, like in picture, you could wrap id of the first object of a group in an array and if a group has more than one object take an array.

const
    data = [{ id: "1", main: [{ type: "a", nu: "0", role: 1 }] }, { id: "2", main: [{ type: "b", nu: "0", role: 2 }] }, { id: "3", main: [{ type: "c", nu: "0", role: 2 }] }, { id: "4", main: [{ type: "d", nu: "0", role: 2 }] }],
    result = data.reduce((r, { id, main }) => {
        main.forEach(({ type, nu, role }) => {
            const key = `${nu.toString().padStart(3, 0)}-${role}`;
            r[key] = r[key]
                ? [].concat(r[key], { id, type })
                : { id: [id], type };
        });
        return r;
    }, {});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

CodePudding user response:

I got your issue, you need to keep a single item just as a JSON (in 0-1), and when there are more than one items they should be inside an array of JSON (in 0-2).

This should fix the issue. Just added an additional check for the above-mentioned case.

const array = [ { id: "1", main: [ { type: "a", nu: "0", role: 1, }, ], }, { id: "2", main: [ { type: "b", nu: "0", role: 2, }, ], }, { id: "3", main: [ { type: "c", nu: "0", role: 2, }, ], }, { id: "4", main: [ { type: "d", nu: "0", role: 2, }, ], }, ];

const result = [
  array.reduce((acc, { id, main }) => {
    const { nu, role, type } = main[0];
    const hash = `${nu.padStart(3, 0)}-${role}`;
    acc[hash] = acc[hash]
      ? Array.isArray(acc[hash]) ? [...acc[hash], { type: type, id: id }] : [acc[hash], { type: type, id: id }]
      : { type, id: [id] }
    return acc;
  }, {}),
];

console.log(JSON.stringify(result, null, 2));

  • Related