user9361329
user9361329

Reputation:

How to create the object based on id and merge the inner key into an array JavaScript

I have a list of product each list have product code, parent id and product name. when I click product I am pushing into an array of an object listed below.

[
   {"pid":"1","pcode":"van","pname":"mobile"},
   {"pid":"1","pcode":"van","pname":"hphone"},
   {"pid":"2","pcode":"car","pname":"wphone"},
   {"pid":"2","pcode":"car","pname":"email"},
   {"pid":"4","pcode":"bus","pname":"sms"}
]

how to create the object group based on id and merge the key3 into an array.

{
   "pid":"1",
   "details":[
      {
         "pcode":"van",
         "pname":["mobile","hphone"]
      }
   ]
},
{
   "pid":"2",
   "details":[
      {
         "pcode":"car",
         "pname":["wphone","email"]
      }
   ]
},
{
   "pid":"3",
   "details":[
      {
         "pcode":"bus",
         "pname":["sms"]
      }
   ]
}

Upvotes: 0

Views: 48

Answers (3)

xdeepakv
xdeepakv

Reputation: 8125

Use .reduce can be done very easily and one for in loop to collect result. faster result

const data = [
    { pid: "1", pcode: "van", pname: "mobile" },
    { pid: "1", pcode: "something", pname: "hphone" },
    { pid: "1", pcode: "van", pname: "hphone" },
    { pid: "2", pcode: "car", pname: "wphone" },
    { pid: "2", pcode: "car", pname: "email" },
    { pid: "4", pcode: "bus", pname: "sms" }
];

let result = data.reduce((map, cur) => {
    if (!map[cur.pid]) {
        map[cur.pid] = {
            pid: cur.pid,
            details: []
        }
    }
    let hasMatch = false
    map[cur.pid].details.forEach(x => {
        if (x.pcode == cur.pcode) {
            hasMatch = true
            x.pname.push(cur.pname)
        }
    })
    if (!hasMatch) {
        map[cur.pid].details.push({
            pcode: cur.pcode,
            pname: [cur.pname]
        })
    }
    return map
}, {})
let finalResult = []
for (const r in result) {
    finalResult.push(result[r])
}
console.log(JSON.stringify(finalResult, null, 4));

Upvotes: 1

StepUp
StepUp

Reputation: 38094

It is possbible to use reduce method to create grouped array by pid. Then we can use map method to assign sequantial pid:

const obj = arr.reduce((a, {pid, pcode, pname}) => {
  a[pid] = a[pid] || {pid, details: []};
  if (a[pid].details.length === 0)
      a[pid].details.push({pcode, pname:[pname]});
  else
      a[pid].details[0].pname.push(pname);
  return a;
}, {})

const result = Object.values(obj).map((v, index) => ({...v, pid: ++index,}))
console.log(result);

An example:

let arr = [
  {"pid":"1","pcode":"van","pname":"mobile"},
  {"pid":"1","pcode":"van","pname":"hphone"},
  {"pid":"2","pcode":"car","pname":"wphone"},
  {"pid":"2","pcode":"car","pname":"email"},
  {"pid":"4","pcode":"bus","pname":"sms"}
];

const obj = arr.reduce((a, {pid, pcode, pname}) => {
  a[pid] = a[pid] || {pid, details: []};
  if (a[pid].details.length === 0)
      a[pid].details.push({pcode, pname:[pname]});
  else
      a[pid].details[0].pname.push(pname);
  return a;
}, {})

const result = Object.values(obj).map((v, index) => ({...v, pid: ++index,}))
console.log(result);

Upvotes: 0

norbitrial
norbitrial

Reputation: 15166

I would use .reduce() for this scenario thus inside you can use .find() to create the desired output. The last pid for bus should be 4 instead of 3 anyway based on the listed array.

Try the following:

const data = [ {"pid":"1","pcode":"van","pname":"mobile"},{"pid":"1","pcode":"van","pname":"hphone"},{"pid":"2","pcode":"car","pname":"wphone"},{"pid":"2","pcode":"car","pname":"email"},    {"pid":"4","pcode":"bus","pname":"sms"}];

const result = data.reduce((a, c) => {
  const found = a.find(e => e.pid === c.pid);
  
  if (found) found.details[0].pname.push(c.pname);
  else a.push({ pid: c.pid, details: [
    { pcode: c.pcode, pname: [ c.pname ] }
  ]});  

  return a;
}, []);

console.log(result);

I hope this helps!

Upvotes: 2

Related Questions