How to extract data from json and inject it into chart? - javascript

I am making a bar chart component which I import in my app.js. My JSON data contains cricket match information i.e season and runs (i.e runs scored in that season). On Y-axis the height of bar will be sum of all the runs in particular season and on X-axis the labels would be the season.
For below JSON example:
season 2008 -> runs = 100+200=300
season 2009 -> runs = 300
season 2010 -> runs = 1100
season 2011 -> runs = 100
JSON data:
[
{
"season":2008,
"runs":100
},
{
"season":2008,
"runs":200
},
{
"season":2009,
"runs":300
},
{
"season":2010,
"runs":600
},
{
"season":2010,
"runs":500
},
{
"season":2011,
"runs":100
}
]
Chart component:
import React, { Component } from 'react';
import ChartistGraph from 'react-chartist';
const ChartData = {
//labels are the season
labels: [ ],
series: [
// runs will be injected here
],
distributeSeries: true
}
const options = {
width: 720,
height: 400
}
class Chart extends Component {
render(){
return(
<div>
<ChartistGraph data={ChartData} type={'Bar'} options={options}/>
</div>
)}
}
export default Chart;
Instead of hardcoding the data from JSON data how can I inject season as labels and runs as series. I tried using for loop but I was not able to get sum of runs for a particular season. eg: for season 2008 it should be 100+200=300 i.e label=2008 and series element corresponding to it will be 300.
Note: For given JSON data series will be :
series:[300, 300, 1100, 100]

using array reduce to combine the seasons, and another reduce to create the two arrays
var json = `[
{
"season":2008,
"runs":100
},
{
"season":2008,
"runs":200
},
{
"season":2009,
"runs":300
},
{
"season":2010,
"runs":600
},
{
"season":2010,
"runs":500
},
{
"season":2011,
"runs":100
}
]`
var data = Object.entries(JSON.parse(json).reduce((acc, {season, runs}) => (acc[season] = (acc[season] || 0) + runs, acc), {}))
.reduce((acc, [labels, series]) => (acc.labels.push(labels), acc.series.push(series), acc),{labels: [], series:[]})
console.log(data)
Broken down in ES5, step by step
var json = `[
{
"season":2008,
"runs":100
},
{
"season":2008,
"runs":200
},
{
"season":2009,
"runs":300
},
{
"season":2010,
"runs":600
},
{
"season":2010,
"runs":500
},
{
"season":2011,
"runs":100
}
]`
var data = JSON.parse(json); // because JSON is a string representation of an javascript object
var data1 = data.reduce(function (acc, item) {
var season = item.season,
runs = item.runs;
acc[season] = acc[season] || 0; // add a season as a key
acc[season] += runs; // add runs
return acc;
}, {});
console.log(data1);
var data2 = Object.entries(data1); // make an array of [[label, runs],[label, runs]...]
console.log(data2);
var data3 = data2.reduce(function (acc, item) { // each item is an array of [year, total runs]
var labels = item[0],
series = item[1];
acc.labels.push(labels);
acc.series.push(series);
return acc;
}, { labels: [], series: [] }); // initialise the return object
console.log(data3);

Create new array, loop through all elements of current array, parse them by their key and see if value is unique in our new array, if it's not add to that, if it is create new element.
function fillGraph(data){
var newArray = []; //creating new, empty array
for(var i = 0; i < data.length; i++){ //going through all elements of data array
if(newArray.hasOwnProperty(data[i]["season"]){ //if it already has that season
newArray["season"] += data[i]["runs"]; //add runs to the current season
}else{
newArray.push({data[i]["season"] : data[i]["runs"]}); //if not create new object with key name as a season name and assign runs
}
}
for(var i in newArray) { //go through our new array
chartData.labels.push(i); //push key name of current array element into graph labels property
chartData.series.push(newArray[i]); //push value of current array element into graph series property
});
}

Sharing my take on the task
<script>
// in the url variable I use a link to my JSON, so might try you by
// firstly uploading your JSON at myjson.com
let url = 'https://api.myjson.com/bins/8x9l7';
fetch(url).then(res => res.json()).then((out) => {
// here you might try console.log(out); to check the correctness of
// displaying your JSON imported via URL
convertJsonToData(out);
}).catch(err => { throw err });
let data = {
labels: [],
series: [[]]
};
function convertJsonToData(jsonData) {
for (let x in jsonData) {
data.labels.push(jsonData[x].transactTime); //transactTime and walletBalance are keys in my JSON, you will have yours
data.series[0].push(jsonData[x].walletBalance);
};
// here you might try console.log(data); to check the correctness of
// data display taken from JSON and modified to use in chart
return data;
};
let options = {
showPoint: false,
lineSmooth: true,
fullWidth: true,
height: 700,
showArea:true,
};
new Chartist.Line('.ct-chart', data, options);
</script>

Related

JavaScript - Targeting an object value to create another variable

So I have an array which looks like this:
[
{ TransactionValues: '50.00' },
{ TransactionValues: '-77.43' },
{ TransactionValues: '-20.23' },
{ TransactionValues: '200.23' }
]
I am trying to find a way to target the monetary value and create a variable based on the sum of these. When I try to target the "50.00" for example I get "Undefined" and it's still an array.
I'm not exactly sure how I can target it specifically, is it possible? Any help would be appreciated
As per the comments here is the full code (be wary I'm still learning so it's not elegant):
var fs = require('fs');
var parse = require('csv-parse');
var transactionValues = []; //Need an array to hold transactions
var currentTrans = [];
var savingsTrans = [];
//constuctor for transactions
function addData (id, accountType, initiatorType, dateTime, transactions) {
var data = {
"AccountID" : id,
"AccountType" : accountType,
"InitiatorType" : initiatorType,
"DateTime" : dateTime,
"TransactionValues" : transactions
}
transactionValues.push(data); //should add a new line
}
function logTrans (accountType, transactions) {
if (accountType == "CURRENT") {
var cTrans = {
"TransactionValues" : transactions
}
currentTrans.push(cTrans);
}
else {
var sTrans = {
"TransactionValues" : transactions
}
savingsTrans.push(sTrans);
}
};
//parses the csv file, loops each row and adds it to the transactionValue array
var parser = parse({columns: true}, function (err, results) {
console.table(results);
for (const row of results) {
addData(row.AccountID, row.AccountType, row.InitiatorType, row.DateTime, row.TransactionValue );
logTrans(row.AccountType, row.TransactionValue);
}
console.log(transactionValues);
console.log(currentTrans);
console.log(savingsTrans);
});
fs.createReadStream(__dirname+'/testData/customer-1234567-ledger.csv').pipe(parser)
not completely following but at the end of the day you have an array like data below.
you can use filter to target the attribute you want.
you can use map to pull out just the values.
you can use reduce to sum them all up.
run the snippet below to see each step
const data = [
{ TransactionValues: '50.00', AccountType: 'CURRENT' },
{ TransactionValues: '-77.43', AccountType: null},
{ TransactionValues: '-20.23', AccountType: 'CURRENT' },
{ TransactionValues: '200.23', AccountType: null }
];
const CurrentTrans = data.filter((x) => x.AccountType === 'CURRENT');
const SavingTrans = data.filter((x) => x.AccountType !== 'CURRENT');
console.log('CurrentTrans');
console.log(CurrentTrans);
console.log('SavingTrans');
console.log(SavingTrans);
const CurrentTransValues = CurrentTrans.map((x) => parseFloat(x.TransactionValues));
const SavingTransValues = SavingTrans.map((x) => parseFloat(x.TransactionValues));
console.log('CurrentTransValues');
console.log(CurrentTransValues);
console.log('SavingTransValues');
console.log(SavingTransValues);
const TotalCurrentValues = CurrentTransValues.reduce((sum, x) => sum + x);
const TotalSavingValues = SavingTransValues.reduce((sum, x) => sum + x);
console.log('TotalCurrentValues');
console.log(TotalCurrentValues.toFixed(2));
console.log('TotalSavingValues');
console.log(TotalSavingValues.toFixed(2));
So I may have fixed it by using parseFloat in my addData and logTrans functions:
function addData (id, accountType, initiatorType, dateTime, transactions) {
var data = {
"AccountID" : id,
"AccountType" : accountType,
"InitiatorType" : initiatorType,
"DateTime" : dateTime,
"TransactionValues" : parseFloat(transactions)
}
transactionValues.push(data); //should add a new line
}
function logTrans (accountType, transactions) {
if (accountType == "CURRENT") {
var cTrans = parseFloat(transactions);
currentTrans.push(cTrans);
}
else {
var sTrans = parseFloat(transactions);
savingsTrans.push(sTrans);
}
};
Now that seems to of worked. So I can use the "Sum values of objects in array" as suggested before. Thank you everyone :)

Javascript get key of nested JSON object?

I have a json response that looks like the image below. I want to get all dates from the json and store in an array.
function buyOption(){
var ticker = document.getElementById('ticker').value;
fetch("https://stock-and-options-trading-data-provider.p.rapidapi.com/options/JPM", {
.then(response => response.json())
.then(data => {
dataset = data;
console.log(dataset['options'])
loadTable()
})
.catch(err => {
console.log(err);
});
function loadTable(){
expiration_dates = []
dates = dataset['options']
// console.log(JSON.parse(dates))
var keys = [];
for(var k in dates) keys.push(k);
console.log(keys)// returns ["0","1","2",3","5",6","9","10","11"]
console.log(dates[0].value) // returns undefined
}
}
goal is to have expiration_dates = ["2020-08-21","2020-08-28"]
You can try this. This will give you only the expiration dates.
var obj = {
"options": [{
"10-2-2001": "",
"someOtherProp": ""
}, {
"20-2-2001": "",
"someOtherProp": ""
}]
}
var expDates = obj.options.map(o=>Object.keys(o)[0])
console.log(expDates)
Refs:
Array.map()
Object.keys()
Try this
let result = dataSet.options.map(x => Object.keys(x));
console.log(result.flat(1))
A simple array map should do the trick and use Object.keys() array to get first key from each object in your data array
const dates = dataset['options'].map(o => Object.keys(o)[0])
console.log(dates)
<script>
const dataset = {
options: [{
'2013-12-22': {
puts: [],
calls: []
}},
{'2013-02-15': {
puts: [],
calls: []
}},
{ '2018-01-01': {
puts: [],
calls: []
}}
]
}
</script>
Something like
const options=dates.options.map(o=>
Object.keys(o).filter(k=>k.match(/^2\d{3}-\d{2}-\d{2}$/))[0]);
The idea is to loop over all options, get all keys for each of the objects and filter out the keys matching the Regexp, which is a date format, starting with 2. From the filtered keys-array I am only interested in the first element ([0]).
for(k in dates) {
keys.push((v=>{
for(let i in v) return i;
})(dates[k]));
}
Try it

How to Convert an Array to JSON on bases on keys like java packages to give a look of tree view

My question is about how to Convert Array to JSON on bases of keys like packages.
I have this array as initial
$scope.myValues = [
{
title:"Transportation",
id:"1",
moduleId:"transportation"
},
{
title:"Bus",
id:"1.1",
moduleId:"transportation.bus"
},
{
title:"Tata Motors",
id:"1.1.1",
moduleId:"transportation.bus.tata.motors"
},
{
title:"Ashok Leyland",
id:"1.1.2",
moduleId:"transportation.bus.ashok.leyland"
},
{
title:"Eicher Motors",
id:"1.1.3",
moduleId:"transportation.bus.eicher.motors"
},
{
title:"Train",
id:"1.2",
moduleId:"transportation.train"
},
{
title:"The Himalayan Queen",
id:"1.2.1",
moduleId:"transportation.train.himQueen"
},
{
title:"Maharaja Deccan Odyssey",
id:"1.2.2",
moduleId:"transportation.train.maharaja.deccan"
},
{
title:"Darjeeling Himalayan Railway",
id:"1.2.3",
moduleId:"transportation.train.darjeeling.himalayan"
}
];
and I want my final array sorted based on keys, like packages keys in java.
$scope.myValues = [{
title:"Transportation",
moduleId:"transportation",
category:[{
title:"Bus",
moduleId:"transportation.bus",
category:[{
title:"Tata Motors",
moduleId:"transportation.bus.tataMotors",
},{
title:"Ashok Leyland",
moduleId:"transportation.bus.ashokLeyland",
},{
title:"Eicher Motors",
moduleId:"transportation.bus.eicherMotors",
}
]
},{
title:"Train",
moduleId:"transportation.train",
category:[{
title:"The Himalayan Queen",
moduleId:"transportation.train.himQueen",
},{
title:"Maharaja Deccan Odyssey",
moduleId:"transportation.train.maharajaDeccan",
},{
title:"Darjeeling Himalayan Railway",
moduleId:"transportation.train.darjeelingHimalayan",
}
]
}];
I have keys like indexing.
My aim is to make a json format object, with a hierarchy structure based on indexing.
Any suggestion no how to convert this array to array like JSON format.
You can create this tree by looping over the data once.
Start with an empty array for our new format
Check out the first item
Split its id by . and cast the path elements to indexes
Split the numeric path in to the last index, and the path towards it
Create a new item, for now without a category property
Navigate through the new format using the numeric path, creating category arrays along the way when needed
When you've reached the deepest/final layer, add to the array using the last index
const data = [{title:"Transportation",id:"1",moduleId:"transportation"},{title:"Bus",id:"1.1",moduleId:"transportation.bus"},{title:"Tata Motors",id:"1.1.1",moduleId:"transportation.bus.tata.motors"},{title:"Ashok Leyland",id:"1.1.2",moduleId:"transportation.bus.ashok.leyland"},{title:"Eicher Motors",id:"1.1.3",moduleId:"transportation.bus.eicher.motors"},{title:"Train",id:"1.2",moduleId:"transportation.train"},{title:"The Himalayan Queen",id:"1.2.1",moduleId:"transportation.train.himQueen"},{title:"Maharaja Deccan Odyssey",id:"1.2.2",moduleId:"transportation.train.maharaja.deccan"},{title:"Darjeeling Himalayan Railway",id:"1.2.3",moduleId:"transportation.train.darjeeling.himalayan"}];
const addModule = (arr, { title, moduleId, id }) => {
const entry = { title, moduleId };
const path = id.split(".").map(Number).map(n => n - 1);
const targetIndex = path[path.length - 1];
const indexes = path.slice(0, -1);
const loc = indexes.reduce(
(arr, i) => {
const next = arr[i];
if (!next.category) next.category = [];
return next.category;
},
arr
);
loc[targetIndex] = entry;
return arr;
}
console.log(
data.reduce(addModule, [])
);

Filling an array in a component with JSON objects Angular 2

I am trying to access keys and values in a JSON response to fill an array. This array is currently blank and is used for chart.js. The API: https://api.coindesk.com/v1/bpi/historical/close.json has keys and values that are changing every 24 hours, i.e.:
{"bpi":
{"2017-10-06":4370.245,
"2017-10-07":4437.0338,
}
}
The array 'data' needs to be filled inside the component.ts file, and not in a template or .html file
chartData = [
{ data: [], label: 'Bitcoin' },
];
To clarify, I am trying to fill the array 'data' with values such as '4370.245' which are coming from an http.get request from the above url.
Try this
chartData = [
{ data: [], label: 'Bitcoin' },
];
let arrayData = chartData[0].data;//this will return you data inside chartData
Edited as per coomment
var outputData = []
var keysArray = Object.keys(tmpObj.bpi)
for (var key in tmpObj.bpi) {
if (tmpObj.bpi.hasOwnProperty(key )) {
outputData.push(tmpObj.bpi[key])
}
}
console.log(outputData);
var tmpObj = {"bpi":
{"2017-10-06":4370.245,
"2017-10-07":4437.0338,
}
};
var outputData = []
var keysArray = Object.keys(tmpObj.bpi)
for (var key in tmpObj.bpi) {
if (tmpObj.bpi.hasOwnProperty(key )) {
outputData.push(tmpObj.bpi[key])
}
}
console.log(outputData);

Firebase orderByChild Ignored

How do I sort the following structure in Firebase by sortOrder?
categories {
{
"b": {
"name": "Banana",
"sortOrder": 2
},
"a": {
"name": "Apple",
"sortOrder": 1
}
}
}
From the documentation it looks as simple as:
ref('categories').orderByChild('sortOrder').once('value') ...
However, the first node returned is banana. It doesn't matter what string value I use. For example, the following returns the same results:
ref('categories').orderByChild('xxx').once('value') ...
Full function:
public list(): Observable<Category[]> {
let ref = firebase.database().ref('categories').orderByChild('sortOrder');
return Observable.fromPromise(<Promise<any>>ref.once('value'))
.flatMap(snapshot => {
let objects = snapshot.val();
let categories: Array<Category> = new Array();
for (let key in objects) {
let category: Category = objects[key];
category.code = key;
categories.push(category);
}
return Observable.of(categories);
}
);
}
The problem is that when you access the children via the snapshot's value's keys, the order is indeterminate.
You need to use the snapshot's forEach method:
return Observable.fromPromise(<Promise<any>>ref.once('value'))
.flatMap(snapshot => {
let categories: Array<Category> = new Array();
snapshot.forEach(childSnapshot => {
let category: Category = childSnapshot.val();
category.code = childSnapshot.key;
categories.push(category);
});
return Observable.of(categories);
}
);
Also, you could just use map and return categories.

Categories

Resources