DEV Community

cristiantsantos
cristiantsantos

Posted on

Help? .map .reduce

I don't know if this is the right place to ask for help, but I've been trying to understand .map and .reduce for 2 days to try to organize my data to insert in my graph but I can't, could you help me?

I need to add the values ​​for each category, I've done it in several ways but I can't get the exact result

My api returns:
(4) [{…}, {…}, {…}, {…}]
0: {name: "test1", category: "Categoria1", price: 3}
1: {name: "test2", category: "Categoria1", price: 13.6}
2: {name: "test3", category: "Categoria2", price: 8}
3: {name: "test4", category: "Categoria2", price: 8}

I need the data as follows to insert in the chart:
[['Categoria1', 16.6],['Categoria2', 16]]

Oldest comments (13)

Collapse
 
ecyrbe profile image
ecyrbe • Edited

I gave a first wrong answer, as i didn't read your spec carrefully.
so here how to do it

const sum = (a, b) => a+b;
const uniqueCategories = (array) => [...new Set(array.map(item => item.category))];

const apiResult = [
  {name: "test1", category: "Categoria1", price: 3},
  {name: "test2", category: "Categoria1", price: 13.6},
  {name: "test3", category: "Categoria2", price: 8},
  {name: "test4", category: "Categoria2", price: 8}
];

const chartData = uniqueCategories(apiResult).map(category => [
  category,
  apiResult
    .filter(item => item.category===category)
    .map(item => item.price)
    .reduce(sum)
]);
console.log(JSON.stringify(chartData));
Collapse
 
cristiantsantos profile image
cristiantsantos

Thank you very much, it helped me a lot, but the graph still doesn't work. =(

It works when I use:
const chartdata1 =[["Category","value"],["Categoria1", 16.6],["Categoria2", 16]]

the code returns the same thing, it's very strange:
[["Category","value"],["Categoria1",16.6],["Categoria2",16]]

*I used the splice to add the header
chartData.splice(0, 0, ["Category","value"])

Collapse
 
cristiantsantos profile image
cristiantsantos

returns: Table has no columns

Thread Thread
 
ecyrbe profile image
ecyrbe

you should post your code, so we can help.

Collapse
 
iambudi profile image
I am Budi • Edited

This kind of question is better placed in stackoverflow.

var data = [
  { name: 'test1', category: 'Categoria1', price: 3 },
  { name: 'test2', category: 'Categoria1', price: 13.6 },
  { name: 'test3', category: 'Categoria2', price: 8 },
  { name: 'test4', category: 'Categoria2', price: 8 },
];

var result = {};
data.forEach(item => {
  const cat = item.category;
  if (result[cat] == undefined) {
    result[cat] = 0;
  }
  result[cat] += item.price;
});

console.log(Object.entries(result));
// output: [['Categoria1', 16.6],['Categoria2', 16]]
// simpler without map reduce
Collapse
 
cristiantsantos profile image
cristiantsantos

Thank you,

where do I find stackoverflow?

Thanks again, but the code didn't work

Collapse
 
iambudi profile image
I am Budi

You can find here stackoverflow.com
For the code that didn't work above try here playcode

Collapse
 
ecyrbe profile image
ecyrbe

For those reading this in the future :

Budi answer is much faster to execute than the one i provided above.

My approach is using functionnal js, no mutated data. For small data tables, it's ok.

But using Budi aproach is much faster if your dataset is large.

Collapse
 
khuongduybui profile image
Duy K. Bui

we can do it purely functional too

const input = [
  {name: "test1", category: "Categoria1", price: 3},
  {name: "test2", category: "Categoria1", price: 13.6},
  {name: "test3", category: "Categoria2", price: 8},
  {name: "test4", category: "Categoria2", price: 8}
];
const map = input
  .map((item) => [item. category, item.price])
  .reduce((result, current) => {
    if (result[current[0]] === undefined) result[current[0]] = 0;
    result[current[0]] += result[current[1]];
    return result;
  }, {});
const output = Object.keys(result).map((key) => [key, result[key]])
Collapse
 
cristiantsantos profile image
cristiantsantos

import React, { useState, useEffect } from "react";
import Chart from "react-google-charts";
import api from '~/services/api';
import { Container } from './styles';
import { startOfDay, endOfDay } from 'date-fns';
function Products() {
const [chartdata1, setChartdata1] = useState([["Category","value"],["Categoria1", 16.6]])
useEffect(() => {
async function loadchart() {
const date1 = startOfDay(new Date())
const date2 = endOfDay(new Date())
const response = await api.get('sales', {
params: { date1, date2 }
});

  const sum = (a, b) => a+b;
  const uniqueCategories = (array) => [...new Set(array.map(item => item.category))];
  const apiResult = [
    {name: "test1", category: "Categoria1", price: 3},
    {name: "test2", category: "Categoria1", price: 13.6},
    {name: "test3", category: "Categoria2", price: 8},
    {name: "test4", category: "Categoria2", price: 8}
  ];
  const chartData = uniqueCategories(apiResult).map(category => [
    category,
    apiResult
      .filter(item => item.category===category)
      .map(item => item.price)
      .reduce(sum)
  ]);

  chartData.splice(0, 0, ["Category","value"])
  console.log(JSON.stringify(chartData));

  setChartdata1(JSON.stringify(chartData))
}
loadchart();

}, []);

Collapse
 
cristiantsantos profile image
cristiantsantos

I'm sorry, I don't know how to post the code correctly.

Thank you very much for the help you are giving me

Collapse
 
ecyrbe profile image
ecyrbe • Edited

just do setChartdata1(chartData)

import React, { useState, useEffect } from "react";
import Chart from "react-google-charts";
import api from '~/services/api';
import { Container } from './styles';
import { startOfDay, endOfDay } from 'date-fns';

// put your independant functions outside your components
const sum = (a, b) => a+b;
const uniqueCategories = (array) => [...new Set(array.map(item => item.category))];


function Products() {
  const [chartdata1, setChartdata1] = useState([["Category","value"],["Categoria1", 16.6]])
  useEffect(() => {
    async function loadchart() {
      const date1 = startOfDay(new Date())
      const date2 = endOfDay(new Date())
      const response = await api.get('sales', {
        params: { date1, date2 }
      });
      const apiResult = [
        {name: "test1", category: "Categoria1", price: 3},
        {name: "test2", category: "Categoria1", price: 13.6},
        {name: "test3", category: "Categoria2", price: 8},
        {name: "test4", category: "Categoria2", price: 8}
      ];
      const chartData = uniqueCategories(apiResult).map(category => [
        category,
        apiResult
          .filter(item => item.category===category)
          .map(item => item.price)
          .reduce(sum)
      ]);
      setChartdata1([["Category","value"],...chartData]);
   }
   loadchart();
  },[]);
Thread Thread
 
cristiantsantos profile image
cristiantsantos

I had done it, really, and it hadn't worked.

Now it worked.

Thank you very much, I don't know how to thank you. I've been in this for 2 days.

Thank you