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. Commented Jan 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 Commented Jan 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);

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

5 Comments

Thank you for the help! If I may ask; which of the solutions would be preferable, and why?
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.
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 Sorry, I didn't see this earlier. I've updated my answer to include that format.
Thank you very much, really appreciated!
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 Comments

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

Comments

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);

Comments

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.