Home > Blockchain >  javascript - organize array of objects based on property of nested array
javascript - organize array of objects based on property of nested array

Time:10-13

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;
    }
    , {});
  • Related