0

I have a $http call with which I retrieve an array of objects. I make three calls to this endpoint and end up with three arrays like the following:

[
  {type: Dog, count: 3}
  {type: Cat, count: 4}
  {type: Elephant, count: 1}
]
[
  {type: Dog, count: 1}
  {type: Cat, count: 9}
]
[
  {type: Dog, count: 19}
  {type: Cat, count: 4}
  {type: Elephant, count: 12}
  {type: Frog, count: 2}

]

The first call is for August stats, the second September, the third October.

What I would like is to then create a dataset that looks like this...

[
  {type:Dog, data:[3,1,9]}
  {type:Cat, data:[4,9,4]}
  {type:Elephant, data:[1. null, 12]}
  {type:Frog, data:[null, null, 2}
]

... so that I can loop through each element with an ngRepeat to display a table of Months/Animals stats.

Anyone have any ideas?

Thanks.

2 Answers 2

1

Because you have to make 3 calls and data structure from server is different than what you are using in angular have used the $q.all to make sure all requests made before merging results. One challenge is that not all animals get returned each month. This took some extra coding to be able to show 0 if animal doesn't exist in amonth.

var app = angular.module('plunker', []);

app.factory('DataService', function($http, $q) {
  /* temp object */
  var tmp = {}, resultsArray = [];


  var DataService = {
    animals: [],
    loadData: function() {

      var def = $q.defer();
      var deferreds = [];
      var requestUrl = ['data1.json', 'data2.json', 'data3.json'];
      for (i = 0; i < requestUrl.length; i++) {    
        var url = requestUrl[i];
        var request = $http.get(url).success(function(res) {
          resultsArray.push(res);

        });
        deferreds.push(request);
      }

      $q.all(deferreds).then(function() {
        def.resolve( mergeResults());
      })

      return def.promise
    }

  }


  function createCountArray() {
    var len = resultsArray.length,
      arr = [];
    while (len) {
      arr.push(0);
      len--
    }
    return arr
  }

  function mergeResults() {
    angular.forEach(resultsArray, function(arr, i) {
      /* create key for all animals, need this because not all animals in each result set */
      angular.forEach(arr, function(item) {
        if (!tmp[item.type]) {
          tmp[item.type] = {type: item.type,count: createCountArray() }
        }
      });
    });

    angular.forEach(resultsArray, function(arr, i) {
      /* now populate counts*/
      angular.forEach(arr, function(item) {
        tmp[item.type].count[i] = item.count;
      });
    });

    /* now map object to array*/

    angular.forEach(tmp, function(val) {
      DataService.animals.push(val);
    });

    return DataService.animals;
  }
  return DataService;

})

app.controller('MainCtrl', function($scope, DataService) {

  DataService.loadData().then(function(res) {
    $scope.animalData = res;
  });    

});

DEMO

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

1 Comment

Thanks Charlie, was using $q already for the $http calls, but the mergeResults() function works well. Added a function to sort by the values in the count array in the animals array too, so all is good. Cheers.
0

What are you looking for is some kind of groupBy operation - you can do your own research using this keyword. My suggestions are:

  • use Javascript's native concat() to merge 3 arrays into one

  • use _.groupBy() function from Underscore.js on merged array.
    This will do the grouping for you.

  • iterate over resulting object to map results according to your needs; Underscore.js _.map() comes in hand

This code snippet is a quick demo of what can be achieved. It works on already merged array.

1 Comment

Cheers Michael, the _.groupBy() defo looks like it should do it. Thanks for the fiddle.

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.