I need to group the data by sub categories, but the property is an array.
I'll appreciate your help, if there is any way to do it with lodash or pure js.
Data Example
const data = [
{
title: "data 1",
sub_categories:[{ id: 1, name: 'gold'},{ id: 2, name: 'water' }]
},
{
title: "data 2",
sub_categories:[{ id: 2, name: 'water'}]
},
{
title: "data 3",
sub_categories:[{ id: 1, name: 'gold'},{ id: 3, name: 'fire' }]
},
{
title: "data 4",
sub_categories:[] // also can be empty
}
]
Code Example
_.chain(data)
.groupBy(props => ) //need help here
.map(({values, key}) => {
return {
values,
key
}
})
.value();
Expected output group by subcategory name (this would be a better solution)
[
{
subcategory: "gold",
list: [{title: "data 1"}, {title: "data: 3"}]
}
]
CodePudding user response:
You could do this in a couple of steps, which you can combine together with _.flow()
:
- Create a new array by flat mapping
sub_categories
. This way we 'expand' the array to now include adata
object for each subcatgory. - Group the flattened/expanded array by the
name
of the subcategory - Map the grouped object to your desired format with
_.map()
const data = [ { title: "data 1", sub_categories:[{ id: 1, name: 'gold'},{ id: 2, name: 'water' }] }, { title: "data 2", sub_categories:[{ id: 2, name: 'water'}] }, { title: "data 3", sub_categories:[{ id: 1, name: 'gold'},{ id: 3, name: 'fire' }] }, { title: "data 4", sub_categories:[] /* also can be empty */} ];
const grp = _.flow(
arr => _.flatMap(arr, obj => _.map(obj.sub_categories, ({name}) => ({...obj, name}))),
flattened => _.groupBy(flattened, 'name'),
grpd => _.map(grpd, (arr, subcategory) => ({subcategory, list: _.map(arr, ({title}) => ({title}))}))
);
console.log(grp(data));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG ljU96qKRCWh quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
CodePudding user response:
var _ = require('lodash');
const data = [
{
title: "data 1",
sub_categories:[{ id: 1, name: 'gold'},{ id: 2, name: 'water' }]
},
{
title: "data 2",
sub_categories:[{ id: 2, name: 'water'}]
},
{
title: "data 3",
sub_categories:[{ id: 1, name: 'gold'},{ id: 3, name: 'fire' }]
},
{
title: "data 4",
sub_categories:[] // also can be empty
}
]
g= _.groupBy(data.map(d=>d.sub_categories.map(s=>({"title":d.title, "name":s.name }))).flat(),"name")
ans=[]
for (const key in g){
ans.push({"subcategory":key,"list": g[key].map(v=>({"title":v.title}))})
}
console.log(
ans
)
You can use above code to get the expected results. groupBy using loadash and other operations done using inbuild functions.
CodePudding user response:
You could group by nested values.
const
data = [{ title: "data 1", sub_categories: [{ id: 1, name: 'gold' }, { id: 2, name: 'water' }] }, { title: "data 2", sub_categories: [{ id: 2, name: 'water' }] }, { title: "data 3", sub_categories: [{ id: 1, name: 'gold' }, { id: 3, name: 'fire' }] }, { title: "data 4", sub_categories: [] }],
result = Object.values(data.reduce((r, { title, sub_categories }) => {
sub_categories.forEach(({ name: subcategory }) => (r[subcategory] ??= { subcategory, list: []}).list.push({ title }));
return r;
}, {}));
console.log(result) ;
.as-console-wrapper { max-height: 100% !important; top: 0; }