Search code examples
angularjslodashangular-nvd3

AngularJS prepare data for MultiBar Chart NVD3


I am calling my API to get JSON array below,

array = [{"date":1533791167870,"count":1,"name":"James"},{"date":1533791167870,"count":3,"name":"Kane"},{"date":1533791167918,"count":1,"name":"Kane"},{"date":1536203856526,"count":2,"name":"Trent"},{"date":1536217871371,"count":5,"name":"Kane"},{"date":1536217882525,"count":4,"name":"James"}]

And my name array,

name_array = ["Kane","Trent","James","Sam"]

I am using Lodash library. I would like to get my output array such that for each date all names are mapped from name_array and if there is count then get count value from array otherwise 0. I am expecting my output array as below result_array,

    result_array = [{
    "date": 1533791167870,
    "count": 1,
    "name": "James"
  }, {
    "date": 1533791167870,
    "count": 3,
    "name": "Kane"
  },
  {
    "date": 1533791167870,
    "count": 0,
    "name": "Trent"
  },
  {
    "date": 1533791167870,
    "count": 0,
    "name": "Sam"
  }, {
    "date": 1533791167918,
    "count": 0,
    "name": "James"
  },
  {
    "date": 1533791167918,
    "count": 1,
    "name": "Kane"
  },
  {
    "date": 1533791167918,
    "count": 0,
    "name": "Sam"
  },
  {
    "date": 1533791167918,
    "count": 0,
    "name": "Trent"
  }, {
    "date": 1536203856526,
    "count": 0,
    "name": "James"
  },
  {
    "date": 1536203856526,
    "count": 0,
    "name": "Kane"
  },
  {
    "date": 1536203856526,
    "count": 2,
    "name": "Trent"
  },
  {
    "date": 1536203856526,
    "count": 0,
    "name": "Sam"
  }, {
    "date": 1536217871371,
    "count": 0,
    "name": "James"
  },
  {
    "date": 1536217871371,
    "count": 5,
    "name": "Kane"
  },
  {
    "date": 1536217871371,
    "count": 5,
    "name": "Trent"
  },
  {
    "date": 1536217871371,
    "count": 5,
    "name": "Sam"
  }, {
    "date": 1536217882525,
    "count": 4,
    "name": "James"
  },
  {
    "date": 1536217882525,
    "count": 0,
    "name": "Trent"
  }, {
    "date": 1536217882525,
    "count": 0,
    "name": "Sam"
  },
  {
    "date": 1536217882525,
    "count": 0,
    "name": "Kane"
  }
]

I am doing this way for NVD3 AngularJS MultiBar chart. Since my array data is not working for the stacked view but group view is working fine. I am using AngularJS, Lodash.

I would appreciate the help.


Solution

  • You can do it with several _.map calls:

    let result = _.flatten(_.map(_.groupBy(array, 'date'), (existedEntries, date) => {
      let usedNames = _.map(existedEntries, entry => entry.name);
      let namesDiff = _.difference(name_array, usedNames);
      let dateNumeric = parseFloat(date);
      let enrichedNames = _.map(namesDiff, name => {
        return {
          date: dateNumeric,
          count: 0,
          name: name
        };
      });
      return _.union(existedEntries, enrichedNames);
    }));
    

    First of all, we group existed entries by date, and for each group determine what names are used there. Then we calculate difference between all possible names and names used in the group. For each name from the difference we map it into default object with count: 0 and date equals to the date of current existing group. Next, we union existing values of the group with ones we got after enriching names diff. Final flatten call removes away temporal internal array structure.

    In case if you use ES5 or lower, replace arrows syntax sugar with functions and let with var, i.e. var usedNames = _.map(existedEntries, function(entry) {return entry.name;});

    P.S. In ES6 you can replace Lodash map function with eponymous native function, i.e. let usedNames = existedEntries.map(entry => entry.name);