How to segregate an array of object based on id

Viewed 80

I have to form an array of object in another array of object based on id. I was able to group the object based the "id" but was not able to group the inside array of object by "code". Please help with this I know its a small fix but I spend whole day still no result. I have also kept the stackblitz link

  const result = this.data.reduce((a, c) => {
      const found = a.find(e => e.id === c.id);
      if (found) found.accessDetails[0].tcode.push(c.tcode);
      else a.push({
        groupId: c.groupId,
        id: c.id, accessDetails: [
          { code: c.code, tcode: [c.tcode] }
        ]
      });
      return a;
    }, []);
    console.log(result);
}

Input:

data = [{groupId: "111", id: "abc", code: "PPL", tcode: "Email"},
{groupId: "111", id: "abc", code: "PPL", tcode: "SMS"},
{groupId: "111", id: "abc", code: "PHL", tcode: "Email"},
{groupId: "111", id: "abc", code: "PHL", tcode: "Mobile"},
{groupId: "222", id: "def", code: "APL", tcode: "Letter"},
{groupId: "222", id: "def", code: "APL", tcode: "SMS"},
{groupId: "222", id: "def", code: "PPL", tcode: "Mobile"},
{groupId: "222", id: "def", code: "PHL", tcode: "Mobile"},
{groupId: "333", id: "ghi", code: "APL", tcode: "Letter"},
{groupId: "333", id: "ghi", code: "PHL", tcode: "SMS"}]

Expexted Output:

[
    {
        "groupId": "111",
        "id": "abc",
        "accessDetails": [
            {
                "code": "PPL",
                "tcode": [
                    "Email"
                    "SMS"
                ]
            },
            {
                "code": "PPL",
                "tcode": [
                    "Email"
                    "Mobile"
                ]
            }
        ]
    },
    {
        "groupId": "222",
        "id": "def",
        "accessDetails": [
            {
                "code": "APL",
                "tcode": [
                    "Letter"
                    "SMS"
                ]
            },
            {
                "code": "PPL",
                "tcode": [
                    "Mobile"
                ]
            }
            {
                "code": "PHL",
                "tcode": [
                    "Mobile"
                ]
            }
        ]
    },
    {
        "groupId": "333",
        "id": "ghi",
        "accessDetails": [
            {
                "code": "APL",
                "tcode": [
                    "Letter"
                ]
            },
            {
                "code": "PHL",
                "tcode": [
                    "Email"
                    "SMS"
                ]
            }
        ]
    }
]

Stackblitz link

3 Answers

Here is one approach. I like to keep the objects keyed by a unique ID during the reduce as long as possible, then use Object.values(...) at the end to clean up and get just arrays based on the result.

const data = [{groupId: "111", id: "abc", code: "PPL", tcode: "Email"},
{groupId: "111", id: "abc", code: "PPL", tcode: "SMS"},
{groupId: "111", id: "abc", code: "PHL", tcode: "Email"},
{groupId: "111", id: "abc", code: "PHL", tcode: "Mobile"},
{groupId: "222", id: "def", code: "APL", tcode: "Letter"},
{groupId: "222", id: "def", code: "APL", tcode: "SMS"},
{groupId: "222", id: "def", code: "PPL", tcode: "Mobile"},
{groupId: "222", id: "def", code: "PHL", tcode: "Mobile"},
{groupId: "333", id: "ghi", code: "APL", tcode: "Letter"},
{groupId: "333", id: "ghi", code: "PHL", tcode: "SMS"}];

const result = Object.values(data.reduce((a, c) => {
  a[c.id] = a[c.id] || {groupId: c.groupId, id: c.id, accessDetails: {}};
  a[c.id].accessDetails[c.code] = a[c.id].accessDetails[c.code] || {
    code: c.code,
    tcode: [],
  };
  a[c.id].accessDetails[c.code].tcode.push(c.tcode);
  return a;
}, {})).map(item => ({...item, accessDetails: Object.values(item.accessDetails)}));

console.log(result);

You can try this

data = [{
    groupId: "111",
    id: "abc",
    code: "PPL",
    tcode: "Email"
  },
  {
    groupId: "111",
    id: "abc",
    code: "PPL",
    tcode: "SMS"
  },
  {
    groupId: "111",
    id: "abc",
    code: "PHL",
    tcode: "Email"
  },
  {
    groupId: "111",
    id: "abc",
    code: "PHL",
    tcode: "Mobile"
  },
  {
    groupId: "222",
    id: "def",
    code: "APL",
    tcode: "Letter"
  },
  {
    groupId: "222",
    id: "def",
    code: "APL",
    tcode: "SMS"
  },
  {
    groupId: "222",
    id: "def",
    code: "PPL",
    tcode: "Mobile"
  },
  {
    groupId: "222",
    id: "def",
    code: "PHL",
    tcode: "Mobile"
  },
  {
    groupId: "333",
    id: "ghi",
    code: "APL",
    tcode: "Letter"
  },
  {
    groupId: "333",
    id: "ghi",
    code: "PHL",
    tcode: "SMS"
  }
]


output = {}

data.forEach(val => {
  if (!output[val.groupId]) {
    output[val.groupId] = {
      groupId: val.groupId,
      id: val.id,
      accessDetails: [{
        code: val.code,
        tcode: [val.tcode]
      }]
    };
  } else {
    const foundIndex = output[val.groupId].accessDetails.findIndex(({
      code
    }) => code === val.code);
    if (foundIndex !== -1) {
      output[val.groupId].accessDetails[foundIndex].tcode.push(val.tcode)
    } else {
      output[val.groupId].accessDetails.push({
        code: val.code,
        tcode: [val.tcode]
      });

    }

  }

})

console.info(Object.values(output));

maybe this will help you.

    const data = [{ groupId: "111", id: "abc", code: "PPL", tcode: "Email" },
    { groupId: "111", id: "abc", code: "PPL", tcode: "SMS" },
    { groupId: "111", id: "abc", code: "PHL", tcode: "Email" },
    { groupId: "111", id: "abc", code: "PHL", tcode: "Mobile" },
    { groupId: "222", id: "def", code: "APL", tcode: "Letter" },
    { groupId: "222", id: "def", code: "APL", tcode: "SMS" },
    { groupId: "222", id: "def", code: "PPL", tcode: "Mobile" },
    { groupId: "222", id: "def", code: "PHL", tcode: "Mobile" },
    { groupId: "333", id: "ghi", code: "APL", tcode: "Letter" },
    { groupId: "333", id: "ghi", code: "PHL", tcode: "SMS" }];

    const tracker = {};
    const result = data.reduce((acc, cur) => {
        let found = tracker[cur.groupId];
        if (!found) {
            found = {
                groupId: cur.groupId,
                id: cur.id,
                accessDetails: [],
            };
            tracker[cur.groupId] = found;
            acc.push(found);
        }

        let details = found.accessDetails.find(x => x.code === cur.code);
        if (!details) {
            details = {
                code: cur.code,
                tcode: []
            };
            found.accessDetails.push(details);
        }
        details.tcode.push(cur.tcode);
        return acc;
    }, []);

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