I'm developing an angular application where I call the following endpoint from CoinGeko API that provides me market charts:
https://api.coingecko.com/api/v3/coins/bitcoin/market_chart?vs_currency=cad&days=7&interval=daily
It returns an like the following:
{
"prices": [
[
1643414400000,
48329.41585141156
],
[
1643494489000,
48870.92050262988
]
],
"market_caps": [
[
1643414400000,
915485662636.434
],
[
1643494489000,
925791491728.014
]
],
"total_volumes": [
[
1643414400000,
24532182816.548737
],
[
1643494489000,
18070713602.083645
]
]
}
From this response, I need to work on the "prices" property only.
It is an array of arrays with UNIX timestamp and the Crypto price.
So what I'm trying to reach is to have two different arrays where:
The following snippet show my attempt:
Interfaces.ts
export interface Chart {
prices: Array<DatePrice>;
market_caps: Array<DatePrice>;
total_volumes: Array<DatePrice>;
}
export interface DatePrice {
unixDate: string[];
price: number[];
}
Component.ts
[...]
coinChart: Chart[];
sevenDayPrices: number[];
sevenDayDates: Date[];
ngOnInit() {
this._apiService
.getWeeklyChartData()
.subscribe(chartData => {
this.coinChart = chartData;
console.log(chartData);
chartData.map(x =>
x.prices.map(daysPrice => {
console.log(daysPrice.price);
this.sevenDayPrices = daysPrice.price
})
);
}
Unfortunately it doesn't work. What I would to achive is something like:
sevendayprices = [48329.4158514115, 48870.92050262988]
sevendaydates = [1643414400000, 1643494489000]
How can I reach this goal?
~SRJ
Looks like what you're doing is pretty much fine. As for the solution, you're receiving Array of arrays, and your Chart interface already contains that. You'd be much better using Array rather than another DatePrice interface bc you don't need it. So first thing first, fix this:
//this is wrong
coinChart: Chart[];
//use this instead
coinChart: Chart;
//since you want in readable date, use
sevenDayDates: string[];//instead of date
Here goes the easiest logic to split both arrays:
ngOnInit() {
this._apiService
.getWeeklyChartData()
.subscribe(chartData => {
this.coinChart = chartData;
this.sevenDayDates = this.coinChart.prices.map(function(tuple) {
return new Date(tuple[0]).toLocaleTimeString()
});
this.sevenDayPrices = this.coinChart.prices.map(function(tuple) {
return tuple[1]
});
}
Let me know if that works. If your interface is proper, you can literally use all these properties in your chartData response. And I hope in the API call, you're returning Chart type rather than Chart[] type.
If I understand your needed well, the following snippet could do the trick:
const response = {
prices: [
[
1643414400000,
48329.41585141156
],
[
1643494489000,
48870.92050262988
]
],
market_caps: [
[
1643414400000,
915485662636.434
],
[
1643494489000,
925791491728.014
]
],
total_volumes: [
[
1643414400000,
24532182816.548737
],
[
1643494489000,
18070713602.083645
]
]
}
...
// Interface
export interface MyObjInterface = {
prices: string[],
dates: string[]
}
...
// inside class, above constructor()
myPrices: number[]
obj: MyObjModel
ngOnInit() {
this.myPrices = response.prices.flat()
this.obj = {
prices: this.checkDotInNumber(myPrices, true),
dates: this.checkDotInNumber(myPrices, false)
}
console.log(this.obj)
}
checkDotInNumber(arr, hasDot): string[] {
const a = arr.flat();
let includeDot = (num) => {
return num.toString().includes('.')
}
return (hasDot) ? a.filter(x => includeDot(x)) : a.filter(x => !includeDot(x))
}
##Explanation:##
You receive an object as response, so you can access to "prices" property just navigating to "response.prices" (with "response" I refer to my object that is the same that you have in your subscription: chartData).
Having "response.prices" you can do some operation on the array and create a new object that I named "this.obj" with two properties: "prices" with the prices array, and "dates" with dates array.
##Why I've created a new object?##
Because "this.myobj" can be destructured so you can quickly and easy access to its property when you need them. So for example:
const {prices, dates} = this.myobj
console.log(prices, dates);
##Hint##:
The object returns two array of string, so if you need to work with number you need to convert elements array to number again.
##UPDATE:##
Based on The Fool comments, he is right, the performance is important, by the way is important find a compromise between performance and readability.
So my other suggestion to achive your goal is:
const mapper = new Map(response.prices);
const prices = Array.from(mapper.values());
const dates = Array.from(mapper.keys());
console.log(dates, prices)
I find this way simpler, fastest and more readable.