I have an nested array of animals
, and I would like to organize them into a map based on the animal
color
.
original data
const animals = [
{
type: 'dog',
species: [
{
name: 'retriever',
color: 'yellow',
},
{
name: 'pug',
color: 'black',
},
{
name: 'lab',
color: 'white',
},
],
},
{
type: 'cat',
species: [
{
name: 'persian',
color: 'white',
},
{
name: 'shorthair',
color: 'black',
},
],
},
];
desired output
const animalsByColor = {
black: [
{
type: 'dog',
species: [
{
name: 'pug',
color: 'black',
},
],
},
{
type: 'cat',
species: [
{
name: 'shorthair',
color: 'black',
},
],
},
],
white: [
{
type: 'dog',
species: [
{
name: 'lab',
color: 'white',
},
],
},
{
type: 'cat',
species: [
{
name: 'persian',
color: 'white',
},
],
},
],
yellow: [
{
type: 'dog',
species: [
{
name: 'retriever',
color: 'yellow',
},
],
},
],
};
CodePudding user response:
see it
const animals = [
{
type: 'dog',
species: [
{
name: 'retriever',
color: 'yellow',
},
{
name: 'pug',
color: 'black',
},
{
name: 'lab',
color: 'white',
},
],
},
{
type: 'cat',
species: [
{
name: 'persian',
color: 'white',
},
{
name: 'shorthair',
color: 'black',
},
],
},
];
const sortedObject = {}
animals.forEach((el)=>{
el.species.forEach((ael)=>{
type = el.type;
name = ael.name;
color = ael.color;
//sorted array
if(!Object.keys(sortedObject).includes(color)){
sortedObject[color] = []
}
data = {
type:type,
species : ael
}
sortedObject[color].push(data)
})
})
console.log(sortedObject)
CodePudding user response:
You could group with the help of an object which keeps the references for color and type.
const
animals = [{ type: 'dog', species: [{ name: 'retriever', color: 'yellow' }, { name: 'pug', color: 'black' }, { name: 'lab', color: 'white' }] }, { type: 'cat', species: [{ name: 'persian', color: 'white' }, { name: 'shorthair', color: 'black' }] }],
references = {},
animalsByColor = {};
animals.forEach(({ type, species }) => {
species.forEach(({ name, color }) => {
references[color] ??= animalsByColor[color] ??= [];
if (!references[color][type]) references[color].push({ type, species: references[color][type] = [] });
references[color][type].push({ name, color });
});
});
console.log(animalsByColor);
.as-console-wrapper { max-height: 100% !important; top: 0; }
CodePudding user response:
If you want to group the animals by color, you will need to iterate over the types and inside each type, the list of species.
For each species, you will need the current loop index to filter the species for each item.
I added a simple example in here as well to showcase the functions extensibility.
const animals = [{
type: 'dog',
species: [
{ name: 'retriever', color: 'yellow' },
{ name: 'pug', color: 'black' },
{ name: 'lab', color: 'white' },
],
}, {
type: 'cat',
species: [
{ name: 'persian', color: 'white' },
{ name: 'shorthair', color: 'black' }
]
}];
const animalsSimple = [
{ type: 'dog', name: 'retriever', color: 'yellow' },
{ type: 'dog', name: 'pug', color: 'black' },
{ type: 'dog', name: 'lab', color: 'white' },
{ type: 'cat', name: 'persian', color: 'white' },
{ type: 'cat', name: 'shorthair', color: 'black' }
];
const main = () => {
const groupedByColor = groupBy(
animals,
({ color }) => color,
'species'
);
console.log(groupedByColor);
const groupedByColorSimple = groupBy(
animalsSimple,
({ color }) => color,
);
console.log(groupedByColorSimple);
};
const groupBy = (items, consumer, subKey) =>
items.reduce((groups, item) => {
if (subKey) {
item[subKey].forEach((subItem, index) => {
applyToGroup(groups, consumer(subItem), item, subKey, index);
});
} else {
applyToGroup(groups, consumer(item), item);
}
return groups;
}, {});
const applyToGroup = (groups, key, item, subKey, index) => {
const items = groups[key] ?? [];
if (subKey) {
items.push({
...item,
[subKey]: item[subKey].filter((_, i) => i === index)
});
} else {
items.push({ ...item });
}
groups[key] = items;
}
main();
.as-console-wrapper { top: 0; max-height: 100% !important; }
CodePudding user response:
Output is a map of colors as keys and an array of animals objects as values grouped by type .
const result = animals.reduce((acc, animalGroup) => {
animalGroup.species.forEach((specie) => {
if (!acc[specie.color]) {
acc[specie.color] = [];
}
acc[specie.color].push(animalGroup.species.filter((animal) => animal.color === specie.color));
});
return acc;
}
, {});