barteloma
barteloma

Reputation: 6855

How to map json array to two different array for chart

I am using chartjs chart in my angular application. And I have using a standart web api result for charts.

this.httpClient.get(this.REST_API_SERVER).subscribe((data: any[])=>{
  console.log(data);

})  

data is:

[
   { "label": "city-1", "data1": 200},
   { "label": "city-2", "data1": 450},
   { "label": "city-2", "data1": 950},
]

or

[
   { "label": "city-1", "data1": 200, "data2": 60 },
   { "label": "city-2", "data1": 450, "data2": 40 },
   { "label": "city-3", "data1": 950, "data2": 78 },
]

I mean, label is label of chart and data1, data2 or data3 is values of chart.

So I want to split this response data to two different array like following.

var labels = [ "city-1", "city-3", "city-3"];
var data = [ 
              { "data": [ 200, 450, 950 ], "label": "data1" },
              { "data": [ 60,  40,  78 ], "label": "data2" }
           ];

is this possible in angular rxjs mapping?

Upvotes: 2

Views: 495

Answers (2)

Wandrille
Wandrille

Reputation: 6811

You can find here a working script:

const list = [
   { "label": "city-1", "data1": 200, "data2": 60 },
   { "label": "city-2", "data1": 450, "data2": 40 },
   { "label": "city-3", "data1": 950, "data2": 78 },
]

const result = list.reduce((acc, item) => {

      const label = item['label'];
      acc[0].push(label);

      const keys = Object.keys(item).filter(key => key !== 'label');
      keys.forEach(key => {
        let labelItem = acc[1].find(value => value.label === key);
        if (!labelItem) {
          acc[1].push({ label:key, data: [item[key]] });
        } else {
          labelItem.data.push(item[key]);
        }
      });

      return acc;
    }, [[], []]);

console.log(result)

For typescript, you will need to add the type.

Upvotes: 1

Nikhil
Nikhil

Reputation: 6643

You can use reduce() to transform the data in required format.

Iterate on given data and if an item with current label exists, then append values to its data array, if not create a new array item with current values.

let input = [
   { "label": "city-1", "data1": 200, "data2": 60 },
   { "label": "city-2", "data1": 450, "data2": 40 },
   { "label": "city-3", "data1": 950, "data2": 78 },
];

let result = input.reduce((acc, curr) => {
  acc.labels = acc.labels || [];
  acc.labels.push(curr.label);
  acc.data = acc.data || [];

  Object.entries(curr).forEach(([key, value]) => {
    if (key !== "label") {
      let item = acc.data.find(item => item.label === key);
      if (item) {
        item.data.push(value);
      } else {
        acc.data.push({
          "data": [value],
          "label": key
        });
      }
    }
  });

  return acc;
}, {});

let labels = result.labels;
let data = result.data;

console.log("Labels", labels);
console.log("Data", data);

Upvotes: 2

Related Questions