Milos
Milos

Reputation: 619

How to group an array of objects by key name?

I have an array of objects and I want to group them by object's key names. I have tried to do this with Array.reduce(), but the result is not good since it's grouped by values. Here is the example of an array I have and example of what I've tried so far

const rawData = [
    {
    "EmailCampaignEvents.campaignRef": "my-first-campaign",
    "EmailCampaignEvents.customerRef": "Customer/0",
    "EmailCampaignEvents.emailRef": "Customer/0",
    "EmailCampaignEvents.eventType": "initial_open",
    "EmailCampaignEvents.occurredAt": "2021-02-25T14:03:04.000"
  },
  {
    "EmailCampaignEvents.campaignRef": "my-second-campaign",
    "EmailCampaignEvents.customerRef": "Customer/123",
    "EmailCampaignEvents.emailRef": "Customer/123",
    "EmailCampaignEvents.eventType": "delivery",
    "EmailCampaignEvents.occurredAt": "2021-03-25T14:03:04.000"
  },
  {
    "Events.occurredAt": "2020-11-11T15:44:07.000",
    "Events.relatedEntityRefFlat": "Customer/6711684",
    "Events.type": "as.commerce.transaction.completed"
  }
];

result = rawData.reduce(function (r, a) {
        r[a["EmailCampaignEvents.eventType"]] = r[a["EmailCampaignEvents.eventType"]] || [];
        r[a["EmailCampaignEvents.eventType"]].push(a);
        r[a["Events.type"]] = r[a["Events.type"]] || [];
        r[a["Events.type"]].push(a);
        return r;
    }, Object.create(null));

console.log(result);

And the result I try to achieve is something like this

{ 
  "EmailCampaignEvents.eventType": [
    {
      "EmailCampaignEvents.campaignRef": "my-first-campaign",
      "EmailCampaignEvents.customerRef": "Customer/0",
      "EmailCampaignEvents.emailRef": "Customer/0",
      "EmailCampaignEvents.eventType": "initial_open",
      "EmailCampaignEvents.occurredAt": "2021-02-25T14:03:04.000"
    },
    {
      "EmailCampaignEvents.campaignRef": "my-second-campaign",
      "EmailCampaignEvents.customerRef": "Customer/123",
      "EmailCampaignEvents.emailRef": "Customer/123",
      "EmailCampaignEvents.eventType": "delivery",
      "EmailCampaignEvents.occurredAt": "2021-03-25T14:03:04.000"
    },
  ],
  "Events.type": [
    {
      "Events.occurredAt": "2020-11-11T15:44:07.000",
      "Events.relatedEntityRefFlat": "Customer/6711684",
      "Events.type": "as.commerce.transaction.completed"
    }
  ]
}

Does anyone know how can I achieve this, but not using lodash or any other library? Any example will be appreciated!

Upvotes: 1

Views: 73

Answers (1)

Nina Scholz
Nina Scholz

Reputation: 386570

You could check if the 'Events.type' exists in the object, then take this string as key for the group, otherwise take 'EmailCampaignEvents.eventType' as key.

const
    rawData = [{ "EmailCampaignEvents.campaignRef": "my-first-campaign", "EmailCampaignEvents.customerRef": "Customer/0", "EmailCampaignEvents.emailRef": "Customer/0", "EmailCampaignEvents.eventType": "initial_open", "EmailCampaignEvents.occurredAt": "2021-02-25T14:03:04.000" }, { "EmailCampaignEvents.campaignRef": "my-second-campaign", "EmailCampaignEvents.customerRef": "Customer/123", "EmailCampaignEvents.emailRef": "Customer/123", "EmailCampaignEvents.eventType": "delivery", "EmailCampaignEvents.occurredAt": "2021-03-25T14:03:04.000" }, { "Events.occurredAt": "2020-11-11T15:44:07.000", "Events.relatedEntityRefFlat": "Customer/6711684", "Events.type": "as.commerce.transaction.completed" }],
    result = rawData.reduce((r, o) => {
        const key = 'Events.type' in o
            ? 'Events.type'
            : 'EmailCampaignEvents.eventType';
            
        (r[key] ??= []).push(o);
        return r;
    }, Object.create(null));

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

Upvotes: 2

Related Questions