Home > Net >  What is the best way to reduce such an array of objects?
What is the best way to reduce such an array of objects?

Time:08-24

I suffer for a long time and do not understand how to filter such an array using the title and size

const items = [
    {title: 'pepperoni', size: 0, count: 1}
    {title: 'pepperoni', size: 1, count: 3}
    {title: 'pepperoni', size: 2, count: 1}
    {title: 'cheese', size: 0, count: 2}
] 

Desired result has unique titles, summed counts and 0 size...

[
    {title: 'pepperoni', size: 0, count: 5}
    {title: 'cheese', size: 0, count: 0}
] // result that i need 

I tried this:

items.filter(obj => obj.title === 'pepperoni' && obj.size === 0) // my last try

I will be very grateful for your help!

CodePudding user response:

reduce() invokes its block parameter for every element in the array, also passing the result of the prior iteration.

A common use of this is to reduce an array to one that contains unique elements, where uniqueness is determined by the block.

const items = [
    {title: 'pepperoni', size: 0, count: 1}
    {title: 'pepperoni', size: 1, count: 3}
    {title: 'pepperoni', size: 2, count: 1}
    {title: 'cheese', size: 0, count: 2}
];

// create an object whose keys are items' titles and values
// include the total count for each
const itemsByTitle = items.reduce((acc, item) => {
  let title = item.title; // by making it a key on acc, title will be unique
  // if it's not a key, make title a key, beginning with 0 count
  if (!acc[title]) acc[title] = { title, count: 0 };
  // increment the count for the title by the element's count
  acc[title].count  = item.count; // for each matching title, add its count
  return acc; // return it, because this is passed to the next iteration
},{} /* see note */);

// note: since there's no "prior iteration" on the first iteration,
// this param tells reduce what to pass to begin

Now itemsByTitle will look like this:

{
  pepperoni: { title:'pepperoni', count: 5 },
  cheese: { title:'cheese', count: 2 }
}

and the OP's desired output will be given by Object.values(itemsByTitle)

Demo

const items = [
  {title: 'pepperoni', size: 0, count: 1},
  {title: 'pepperoni', size: 1, count: 3},
  {title: 'pepperoni', size: 2, count: 1},
  {title: 'cheese', size: 0, count: 2}
];

const itemsByTitle = items.reduce((acc, item) => {
  let title = item.title;
  if (!acc[title]) acc[title] = { title, count: 0 };
  acc[title].count  = item.count;
  return acc;
},{});

console.log(Object.values(itemsByTitle))

CodePudding user response:

You are unclear about what do you want your items to be filtered by. The only common thing I can see in the items within your "result" array is that both items have a size of 0 so I assume that's what you are trying to filter by which is quite simple:

const result = items.filter((item) => item.size === 0)

  • Related