Dogukan Karabeyin
Dogukan Karabeyin

Reputation: 31

Javascript group objects by value

Firstly I need to group an array of object with respect to policy attribute's value. Then I need to group action and company fields. I tried to use lodash but could not get to the nested arrays.

From this =>

[
    {
        "action": "VIEW",
        "policy": "FORM"
    },
    {
        "action": "CREATE",
        "policy": "USER"
    },
    {
        "action": "VIEW",
        "policy": "USER"
    },
    {
        "company": "Microsoft",
        "policy": "FORM"
    },
    {
        "company": "Facebook",
        "policy": "USER"
    },
    {
        "company": "Twitter",
        "policy": "USER"
    }
]

to this =>

{
    "FORM": {
            "action": ["VIEW"],
            "company": ["Microsoft"]
        },
    "USER": {
            "action": ["CREATE", "VIEW"],
            "company": ["Facebook", "Twitter"]
        }
}

Thanks a lot

Upvotes: 2

Views: 103

Answers (4)

Souhail HARRATI
Souhail HARRATI

Reputation: 325

You can use lodash library for this solution :


const content = {
    "success": 1,
    "data": [
        {
            "clustername": "c2",
            "monthday": "12/29"
        },
        {
            "clustername": "C3",
            "monthday": "12/29"
        },
        {
            "clustername": "C71",
            "monthday": "12/31"
        },
        {
            "clustername": "C34",
            "monthday": "12/31"
        },
        {
            "clustername": "C998",
            "monthday": "1/4"
        },
        {
            "clustername": "C99",
            "monthday": "1/4"
        }
    ]
};
function customName(n) {
  return {name:n.clustername};
}


const array =  _.chain(content.data)
    .groupBy("monthday")
    .map((value, key) => ({ name: key, children:  _.map(value,v => customName(v))
    }))
    .value()
console.log(array);

Upvotes: 0

BIPUL MANDOL
BIPUL MANDOL

Reputation: 289

By this function, you can group by any field value .

const groupBy = (x, f) => x.reduce((a, b) => ((a[f(b)] ||= []).push(b), a), {})

For group by policy

groupBy(data, v => v.policy)

Upvotes: 0

lejlun
lejlun

Reputation: 4427

You can do this using a simple for...of loop and some destructuring:

const data = [ { action: 'VIEW', policy: 'FORM', }, { action: 'CREATE', policy: 'USER', }, { action: 'VIEW', policy: 'USER', }, { company: 'Microsoft', policy: 'FORM', }, { company: 'Facebook', policy: 'USER', }, { company: 'Twitter', policy: 'USER', }, ];
let result = {};

for (const { action, policy, company } of data) {
  result[policy] = result[policy] ?? { action: [], company: [] };
  if (action) result[policy].action.push(action);
  if (company) result[policy].company.push(company);
}

console.log(result);

You could also do this using array#reduce instead of a for loop:

const data = [ { action: 'VIEW', policy: 'FORM' }, { action: 'CREATE', policy: 'USER' }, { action: 'VIEW', policy: 'USER' }, { company: 'Microsoft', policy: 'FORM' }, { company: 'Facebook', policy: 'USER' }, { company: 'Twitter', policy: 'USER' }, ];

const result = data.reduce((result, { action, company, policy }) => {
  result[policy] = result[policy] ?? { action: [], company: [] };
  action && result[policy].action.push(action);
  company && result[policy].company.push(company);
  return result;
}, {});

console.log(result);

Upvotes: 3

Nina Scholz
Nina Scholz

Reputation: 386883

You could group by policy and separate the rest of the array and build nested groups.

const
    data = [{ action: "VIEW", policy: "FORM" }, { action: "CREATE", policy: "USER" }, { action: "VIEW", policy: "USER" }, { company: "Microsoft", policy: "FORM" }, { company: "Facebook", policy: "USER" }, { company: "Twitter", policy: "USER" }],
    result = Object.values(data.reduce((r, { policy, ...o }) => {
        r[policy] ??= {};
        Object
            .entries(o)
            .forEach(([k, v]) => (r[policy][k] ??= []).push(v));
        return r;
    }, {}));

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

Upvotes: 0

Related Questions