1

I am trying to extract data from JSON data using .map() in javascript. The data extract needs to injected in stacked bar chart .

I am trying to do similar to this question : Stacked bar charts in Chart.js with JSON data but in my case I want total runs per season that will be the height of barchart and the total height of stacked-barchart will be divided into 3 stacks.

check this for stacked bar chart: https://gionkunz.github.io/chartist-js/examples.html#stacked-bar

My JSON data:

        const batdata=[
    {"season":2008,
     "runs":25,
     "tournamentName":"XYZ"
    },
    {"season":2008,
     "runs":125,
     "tournamentName":"ABC"
    },
    {"season":2008,
     "runs":825,
     "tournamentName":"PQR"
    },
    {"season":2009,
     "runs":425,
     "tournamentName":"XYZ"
    },
    {"season":2009,
     "runs":255,
     "tournamentName":"ABC"
    },
    {"season":2010,
     "runs":275,
     "tournamentName":"XYZ"
    },
    {"season":2010,
     "runs":675,
     "tournamentName":"ABC"
    }
 ];
    export default batdata;

In chart.js:

import React, { Component } from 'react';
import batdata from './batdata';

const uniq = a => [...new Set(a)]

const uniqueseason = uniq(

  batdata.map( newdata => newdata.season)

)

const runsperseason = batdata.map( newdata => {

})

class Chart extends Component {

  render(){
    return(
      <div>    

      </div>
    )}

}

export default Chart;

I am using .map() to get unique season and then again nested map() to get runs for particular season for particular tournamentName. How can I parse the data external json file. The final data should look like this:

labels  = [2008,2009 2010]

Chartdata = [
    [25, 125, 825]  <--- Height of barchart = 825+25+125 and it will have 3 stacks because there are 3 tournamentName 
    [425, 255, 0]   <-- tournamentName: PQR not present in season 2009 so 3rd element zero
    [275, 675, 0]   <---tournamentName: PQR not present in season 2010 so 3rd element zero
]

I want to extract the data and store it in 3 data in the form of 3 arrays:

1)Runs in season 2008 for tournamentName: XYZ,ABC, PQR
2)Runs in season 2009 for tournamentName: XYZ, ABC, PQR
3)Runs in season 2010 for tournamentName: XYZ, ABC, PQR

After storing data in 3 different arrays we can just use destructuring operator ... to unpack array elements and populate the chartdata.

8
  • Your chart data grouping is by season, however, in comments you are saying by tournamentName. Please clarify on this Commented Jun 6, 2018 at 5:48
  • @NikhilAggarwal Check edited question. Commented Jun 6, 2018 at 5:48
  • PQR not present in season 2009 so 3rd element zero - shouldn't second element be zero? Commented Jun 6, 2018 at 5:50
  • @NikhilAggarwal There are 3 seasons and each season haas 3 tournamentName. Commented Jun 6, 2018 at 5:50
  • @NikhilAggarwal 3rd tournment name is PQR as XYZ AND ABC are present Commented Jun 6, 2018 at 5:51

2 Answers 2

2

You can try following

const batdata=[{"season":2008,"runs":25,"tournamentName":"XYZ"},{"season":2008,"runs":125,"tournamentName":"ABC"},{"season":2008,"runs":825,"tournamentName":"PQR"},{"season":2009,"runs":425,"tournamentName":"XYZ"},{"season":2009,"runs":255,"tournamentName":"ABC"},{"season":2010,"runs":275,"tournamentName":"XYZ"},{"season":2010,"runs":675,"tournamentName":"ABC"}];
 
// Create set for unique tournament names
let tournaments = new Set();

/* Create an object with key as season name and value as object with 
** tournament name as key and run as value */
let obj = batdata.reduce((a,{season, runs, tournamentName}) => {
 a[season] = a[season] || {};
 a[season][[tournamentName]] = runs;
 tournaments.add(tournamentName);
  return a;
 },{});
 
// Create array from set of unique tournament names
 tournaments = Array.from(tournaments);
 
 // Get the labels - seasons
 let labels = Object.keys(obj);

 // Get the data
 let chartData = Object.values(obj);
 
 // Set runs as 0 for missing tournament in the season
 chartData = chartData.map((o) => tournaments.reduce((a,t) => [...a, o[t] ? o[t] : 0], []));

 console.log(labels);
 console.log(chartData);

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

7 Comments

I am new to reduce(). I have few doubts: 1) ,{}); -> this returns an object from reduce() is it true ? and 2) Can you explain this (a,{season, runs, tournamentName}). Also what is accumulator and currentValue in above code. It would be helpful if you add it in your answer
@stonerock - reduce return the accumulator. In the above code it is at 2 places - one return an object and second returns an array. Hence, it can be anything depending upon what needs to be aggregated. In the said code a is the accumulator and {season, runs, tournamentName} is the currentValue. For reference - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Also, read Unpacking fields from objects passed as function parameter section under developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… . I hope it clarifies
What is this line -> a[season] = a[season] || {}; ?
@stonerock - It means assign a[season] to an empty {} for the first time as a[season] will not exist and then as it exists keep the same value. It is like setting default value.
|
2

You can create map to define such filtered object using Array#reduce.

let filterData = batdata.reduce((filter, value, index) => {

    if (filter[value.season]) {
        filter[value.season] = [...filter[value.season], value.season];
    } else {
        filter[value.season] = [value.season];
    }

    return filter;
}, {});

console.log(filterData)

Working codesandbox#demo

2 Comments

Can it be done using nested .map() and .find() as I am not familiar with .reduce()
it can be.But reduce is can do things done by map and find and other also array utility.

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.