0

I am trying to loop through an array of arrays with object [[{},{},{}],[{},{},{}]], and create a new array that basically "totals" the arrays. I am a bit at a loss on how to achieve this.

My data looks like this:

[ [{ "2017-01-05": 607 }, { "2017-01-06": 430 }, { "2017-01-07": 357 }, { "2017-01-08": 277 }], [{ "2017-01-09": 607 }, { "2017-01-10": 430 }, { "2017-01-11": 357 }, { "2017-01-12": 277 }] ], 

I would like to "count" and "label" each week, and total each week. Example:

newArray: [{"Week 1": 1075}, {"Week 2": 1590}] 

I know I should probably use a forEach loop, but then it gets a bit sketchy:

dateArray.forEach( function (arrayWeek) { // push and name etc. functionality }); 

I would greatly appreciate your assistance and guidance.

2
  • 2
    It's going to be difficult, as you need to define what constitutes a 'week', and when it begins. Otherwise, I'd suggest using reduce rather than forEach() if I get time today I'll try to get an answer up for you.
    – rrd
    CommentedJan 12, 2017 at 11:48
  • Thank you, that will be great! The way to determine the start of a week, would probably be the start of a new array. I think! :D
    – onmyway
    CommentedJan 12, 2017 at 11:54

4 Answers 4

3

I would use the map function and reduce each week inside the map:

var days = [ [{"2017-01-05":607}, {"2017-01-06":430}, {"2017-01-07":357}, {"2017-01-08":277}], [{"2017-01-09":607}, {"2017-01-10":430}, {"2017-01-11":357}, {"2017-01-12":277}] ]; function aggregator(memo, day) { for (var i in day) { memo += day[i]; } return memo; } // Original version from the question var weeks = days.map(function(week, index) { var obj = {}; obj['Week ' + (index + 1)] = week.reduce(aggregator, 0); return obj; }); console.log(weeks); // Follow up version from question in the comments var weeks2 = days.map(function(week, index) { return { name: 'week ' + (index + 1), total: week.reduce(aggregator, 0) }; }); console.log(weeks2);

5
  • Thank you for the help! If I may ask; which of the solutions would be preferable, and why?
    – onmyway
    CommentedJan 12, 2017 at 12:10
  • 1
    Either will do what you want it to. Personally, I think mine is easier to read but that's probably the only real difference. There may be some performance differences but I doubt they would be enough to choose one over the other unless you are running this on a very large array very frequently.
    – rdubya
    CommentedJan 12, 2017 at 12:13
  • I apologize for asking this now, but how would I be able to modify your solution to change the output to look like this: [{"name": "week 1", "total": 1595}, {"name": "week 2", "total": 2075}] ?
    – onmyway
    CommentedJan 12, 2017 at 13:03
  • 1
    @onmyway Sorry, I didn't see this earlier. I've updated my answer to include that format.
    – rdubya
    CommentedJan 13, 2017 at 1:17
  • Thank you very much, really appreciated!
    – onmyway
    CommentedJan 13, 2017 at 5:48
2

You can try something like this.

var data=[[{"2017-01-05":607},{"2017-01-06":430},{"2017-01-07":357},{"2017-01-08":277}],[{"2017-01-09":407},{"2017-01-10":430},{"2017-01-11":357},{"2017-01-12":277}]]; var result = data.reduce(function(p, c, i) { var total = c.reduce(function(total, obj) { for (var k in obj) { total += obj[k]; } return total; }, 0); // Format object in any format you want var tmp = {}; tmp.name = "Week " + (i+1) tmp.total = total; // Push formatted object in array p.push(tmp) return p; }, []) console.log(result)

Note, I'd suggest you to use an object instead of array of objects. Benefit of this would be that you will not require to loop over output to get value. You can directly so result['week'+index]

var data=[[{"2017-01-05":607},{"2017-01-06":430},{"2017-01-07":357},{"2017-01-08":277}],[{"2017-01-09":407},{"2017-01-10":430},{"2017-01-11":357},{"2017-01-12":277}]]; var result = data.reduce(function(p, c, i) { var total = c.reduce(function(total, obj) { for (var k in obj) { total += obj[k]; } return total; }, 0); p["week" + (i + 1)] = total; return p; }, {}) console.log(result)

5
  • How would I be able to modify your solution to change the push to look like this: {"name": "week 1", "total": 595} ?
    – onmyway
    CommentedJan 12, 2017 at 12:59
  • 1
    @onmyway I'm pushing tmp in array. Just update this object and you are good to go
    – Rajesh
    CommentedJan 12, 2017 at 13:01
  • Thank you, I will give it a shot!
    – onmyway
    CommentedJan 12, 2017 at 13:03
  • Do I edit this line, and can you perhaps help with the dbl and single quotes blush? tmp['"name": "week " + (i + 1),"total": total'];
    – onmyway
    CommentedJan 12, 2017 at 13:20
  • Thank you very much, Rajesh! i cannot believe i hit a blank like that - I have done this before, really. :D
    – onmyway
    CommentedJan 13, 2017 at 5:51
1

the variable weeks should hold what you want... I'm assuming the week number is the actual week number in the year and not some index in the array. I'd also not use the same data structure but am adapting so that you won't need to change your structure.

var arr = [ [{ "2017-01-05": 607 }, { "2017-01-06": 430 }, { "2017-01-07": 357 }, { "2017-01-08": 277 }], [{ "2017-01-09": 607 }, { "2017-01-10": 430 }, { "2017-01-11": 357 }, { "2017-01-12": 277 }] ] function week(d) { // taken from http://stackoverflow.com/questions/6117814/get-week-of-year-in-javascript-like-in-php d.setHours(0, 0, 0, 0); d.setDate(d.getDate() + 4 - (d.getDay() || 7)); return Math.ceil((((d - new Date(d.getFullYear(), 0, 1)) / 8.64e7) + 1) / 7); } var weeks = {}; for (var x in arr) { var subarr = arr[x] for (var y in subarr) { var obj = subarr[y]; for (var when in obj) { var d = new Date(when); var which_week = "Week " + week(d); if (which_week in weeks) { weeks[which_week] += obj[when]; } else { weeks[which_week] = obj[when]; } } } } 
0
    0

    without forEach

    var arrs = [ [{ "2017-01-05": 607 }, { "2017-01-06": 430 }, { "2017-01-07": 357 }, { "2017-01-08": 277 }], [{ "2017-01-09": 607 }, { "2017-01-10": 430 }, { "2017-01-11": 357 }, { "2017-01-12": 277 }] ]; function loop1(arr, i, r){ r = (r ? r : 0) + arr[i][Object.keys(arr[i])[0]]; return ++i == arr.length ? r : loop1(arr, i, r); } function loop2(arrs, i, r){ i = i ? i : 0; r = r ? r : {}; r['Week ' + (i + 1)] = loop1(arrs[i], 0); return ++i == arrs.length ? r : loop2(arrs, i, r); } var newArr = loop2(arrs); 

      Start asking to get answers

      Find the answer to your question by asking.

      Ask question

      Explore related questions

      See similar questions with these tags.