1

I have an array like this:

const fruits = [ 
    { fruit: 'apple',  year: 2018 },
    { fruit: 'apple',  year: 2018 },
    { fruit: 'banana', year: 2018 },
    { fruit: 'orange', year: 2018 },
    { fruit: 'apple',  year: 2017 },
    { fruit: 'apple',  year: 2016 }
];

Now I want to reduce this array to see how many fruits there are each year and how much the total is. So that the result looks like this:

const result = [ 
    { year: 2018, apple: 2, banana: 1, orange: 1 total: 4 },
    { year: 2017, apple: 1, total: 1 },
    { year: 2016, apple: 1, total: 1 }
];

I have tried with reduce, but I couldn't figure out how to group it based on the year. Maybe there is also a lodash helper?

3 Answers 3

4

Use Object.values and reduce

var output = Object.values(fruits.reduce( (a,c) => {
  a[c.year] = a[c.year] || { year : c.year };  
  a[c.year]["total"] = (a[c.year]["total"] || 0) + 1;
  a[c.year][c.fruit] = (a[c.year][c.fruit] || 0) + 1;
  return a;
},{}));

Demo

var fruits = [{
    fruit: 'apple',
    year: 2018
  },
  {
    fruit: 'apple',
    year: 2018
  },
  {
    fruit: 'banana',
    year: 2018
  },
  {
    fruit: 'orange',
    year: 2018
  },
  {
    fruit: 'apple',
    year: 2017
  },
  {
    fruit: 'apple',
    year: 2016
  }
];

var output = Object.values(fruits.reduce((a, c) => {
  a[c.year] = a[c.year] || {
    year: c.year
  };
  a[c.year]["total"] = (a[c.year]["total"] || 0) + 1;
  a[c.year][c.fruit] = (a[c.year][c.fruit] || 0) + 1;
  return a;
}, {}));

console.log(output);

Sign up to request clarification or add additional context in comments.

Comments

1

You can use array#reduce to group your data based on year and count the fruit occurrence in an object accumulator. Then get all the values from this object using Object.values()

const fruits = [ { fruit: 'apple', year: 2018 }, { fruit: 'apple', year: 2018 }, { fruit: 'banana', year: 2018 }, { fruit: 'orange', year: 2018 }, { fruit: 'apple', year: 2017 }, { fruit: 'apple', year: 2016 } ],
    result = Object.values(fruits.reduce((r,{fruit, year}) => {
      r[year] = r[year] || {year};
      r[year][fruit] = (r[year][fruit] || 0) + 1;
      r[year]['total'] = (r[year]['total'] || 0) + 1;
      return r;
    },{}));
console.log(result);

Comments

0

You could use an array as result set, which keeps the given order of the year.

var fruits = [{ fruit: 'apple',  year: 2018 }, { fruit: 'apple',  year: 2018 }, { fruit: 'banana', year: 2018 }, { fruit: 'orange', year: 2018 }, { fruit: 'apple',  year: 2017 }, { fruit: 'apple',  year: 2016 }],
    result = fruits.reduce((r, { year, fruit }) => {
        var item = r.find(o => o.year === year);
        if (!item) {
            r.push(item = { year });
        }
        item[fruit] = (item[fruit] || 0) + 1;
        return r;
    }, []);
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.