Related
I am creating a query in MongoDB which works correctly for me but in the end I have to do an extra grouping to get the response grouped by year. This is the query:
db.sales.aggregate([
{
$group: {
_id: {
month: {
$month: "$createdAt"
},
year: {
$year: "$createdAt"
},
dayOfWeek: {
$dayOfWeek: "$createdAt"
},
stringDay: {
$dateToString:
{ format: "%Y-%m-%d", date: "$createdAt"}
},
week: {
$isoWeek: "$createdAt"
}
},
total: { $sum: '$total'},
count: { $sum: 1 },
totalAverage: { $avg: '$total'}
}
},
{
$sort : {
"_id.month" : 1
}
},
{
$project: {
total: { $round: [ "$total", 2 ] },
year: "$_id.year",
date: "$_id.date",
week: "$_id.week",
numVentas: "$count",
month: "$_id.month",
dayOfWeek: "$_id.dayOfWeek",
stringDay:"$_id.stringDay",
count: "$count",
totalAverage: { $round: [ "$totalAverage", 2 ] },
stringMonth: {
$arrayElemAt: [
[
"",
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
],
"$_id.month"
]
},
stringWeek: {
$switch: {
branches:[
{ case: { $eq: ["$_id.dayOfWeek", 1] }, then: "Lunes" },
{ case: { $eq: ["$_id.dayOfWeek", 2] }, then: "Martes" },
{ case: { $eq: ["$_id.dayOfWeek", 3] }, then: "Miércoles" },
{ case: { $eq: ["$_id.dayOfWeek", 4] }, then: "Jueves" },
{ case: { $eq: ["$_id.dayOfWeek", 5] }, then: "Viernes" },
{ case: { $eq: ["$_id.dayOfWeek", 6] }, then: "Sábado" },
{ case: { $eq: ["$_id.dayOfWeek", 7] }, then: "Domingo" }
],
default: "Día desconocido"
}
}
}
},
{
$group: {
_id: { month: "$stringMonth", year: "$year"},
count: { $sum: "$count" },
total: { $sum: "$total" },
totalAverage: { $sum: "$totalAverage" },
sales: {
$push: {
numberDay: "$dayOfWeek",
stringWeek: "$stringWeek",
date: "$stringDay",
total: "$total",
count: "$count",
totalAverage: { $round: [ "$totalAverage", 2 ] }
}
}
}
},
{
$group: {
_id: "$_id.year",
monthsWithSales: { $sum: 1 },
count: { $sum: "$count" },
total: { $sum: "$total" },
totalAverage: { $sum: "$totalAverage" },
sales: {
$push: {
mes: "$_id.month",
count: "$count",
total: "$total",
totalAverage: "$totalAverage",
sales:"$sales"
}
}
}
}
])
And I get this response:
[
{
"_id": 2022,
"monthsWithSales": 4,
"count": 57,
"total": 22324.8,
"totalAverage": 7765.799999999999,
"sales": [
{
"mes": "Oct",
"count": 10,
"total": 1936,
"totalAverage": 1233.6,
"sales": [
{
"numberDay": 6,
"stringWeek": "Sábado",
"date": "2022-10-21",
"total": 526.8,
"count": 3,
"totalAverage": 175.6
},
{
"numberDay": 1,
"stringWeek": "Lunes",
"date": "2022-10-02",
"total": 85.6,
"count": 1,
"totalAverage": 85.6
},
{
"numberDay": 7,
"stringWeek": "Domingo",
"date": "2022-10-22",
"total": 526.8,
"count": 3,
"totalAverage": 175.6
},
{
"numberDay": 3,
"stringWeek": "Miércoles",
"date": "2022-10-04",
"total": 180,
"count": 1,
"totalAverage": 180
},
{
"numberDay": 4,
"stringWeek": "Jueves",
"date": "2022-10-12",
"total": 531.2,
"count": 1,
"totalAverage": 531.2
},
{
"numberDay": 3,
"stringWeek": "Miércoles",
"date": "2022-10-25",
"total": 85.6,
"count": 1,
"totalAverage": 85.6
}
]
},
{
"mes": "Nov",
"count": 7,
"total": 2205.2,
"totalAverage": 1014.8,
"sales": [
{
"numberDay": 4,
"stringWeek": "Jueves",
"date": "2022-11-02",
"total": 526.8,
"count": 3,
"totalAverage": 175.6
},
{
"numberDay": 6,
"stringWeek": "Sábado",
"date": "2022-11-25",
"total": 171.2,
"count": 2,
"totalAverage": 85.6
},
{
"numberDay": 7,
"stringWeek": "Domingo",
"date": "2022-11-12",
"total": 1507.2,
"count": 2,
"totalAverage": 753.6
}
]
},
{
"mes": "Dec",
"count": 33,
"total": 12587.6,
"totalAverage": 4074.5,
"sales": [
{
"numberDay": 3,
"stringWeek": "Miércoles",
"date": "2022-12-06",
"total": 850,
"count": 1,
"totalAverage": 850
},
{
"numberDay": 6,
"stringWeek": "Sábado",
"date": "2022-12-02",
"total": 8737.6,
"count": 25,
"totalAverage": 349.5
},
{
"numberDay": 7,
"stringWeek": "Domingo",
"date": "2022-12-10",
"total": 900,
"count": 1,
"totalAverage": 900
},
{
"numberDay": 1,
"stringWeek": "Lunes",
"date": "2022-12-04",
"total": 200,
"count": 1,
"totalAverage": 200
},
{
"numberDay": 2,
"stringWeek": "Martes",
"date": "2022-12-05",
"total": 500,
"count": 1,
"totalAverage": 500
},
{
"numberDay": 5,
"stringWeek": "Viernes",
"date": "2022-12-08",
"total": 250,
"count": 2,
"totalAverage": 125
},
{
"numberDay": 4,
"stringWeek": "Jueves",
"date": "2022-12-07",
"total": 250,
"count": 1,
"totalAverage": 250
},
{
"numberDay": 6,
"stringWeek": "Sábado",
"date": "2022-12-09",
"total": 900,
"count": 1,
"totalAverage": 900
}
]
},
{
"mes": "Sep",
"count": 7,
"total": 5596,
"totalAverage": 1442.8999999999999,
"sales": [
{
"numberDay": 2,
"stringWeek": "Martes",
"date": "2022-09-12",
"total": 5069.2,
"count": 4,
"totalAverage": 1267.3
},
{
"numberDay": 6,
"stringWeek": "Sábado",
"date": "2022-09-02",
"total": 526.8,
"count": 3,
"totalAverage": 175.6
}
]
}
]
},
{
"_id": 2021,
"monthsWithSales": 1,
"count": 2,
"total": 608,
"totalAverage": 608,
"sales": [
{
"mes": "Dec",
"count": 2,
"total": 608,
"totalAverage": 608,
"sales": [
{
"numberDay": 1,
"stringWeek": "Lunes",
"date": "2021-12-12",
"total": 171.2,
"count": 1,
"totalAverage": 171.2
},
{
"numberDay": 4,
"stringWeek": "Jueves",
"date": "2021-12-22",
"total": 436.8,
"count": 1,
"totalAverage": 436.8
}
]
}
]
}
]
It is correct, but as you can see at the end I make two groups to obtain the data grouped by year and then the sales array grouped by month.
Is there any way to improve this query without so much grouping?
I'm looking to perform some data manipulation of an object/array by somewhat transposing the values. where the values of the rows become columns. As an example i have original data which looks like this
[
{
"Team": "D PG",
"Original_x0020_Size_x0020__x0028": 194,
"Month": "January"
},
{ "Team": "D PP",
"Original_x0020_Size_x0020__x0028": 143,
"Month": "January"
},
{
"Team": "D RE",
"Original_x0020_Size_x0020__x0028": 19,
"Month": "January"
},
{
"Team": "D GP",
"Original_x0020_Size_x0020__x0028": 3,
"Month": "January"
},
{
"Team": "D PC",
"Original_x0020_Size_x0020__x0028": 2,
"Month": "January"
},
{
"Team": "D PT",
"Original_x0020_Size_x0020__x0028": 2,
"Month": "January"
},
{
"Team": "D PG",
"Original_x0020_Size_x0020__x0028": 35,
"Month": "February"
},
{
"Team": "D PP",
"Original_x0020_Size_x0020__x0028": 120,
"Month": "February"
},
{
"Team": "D RE",
"Original_x0020_Size_x0020__x0028": 40,
"Month": "February"
},
{
"Team": "D GP",
"Original_x0020_Size_x0020__x0028": 30,
"Month": "February"
},
{
"Team": "D PC",
"Original_x0020_Size_x0020__x0028": 9,
"Month": "February"
},
{
"Team": "D PT",
"Original_x0020_Size_x0020__x0028": 6,
"Month": "February"
}
]
My intention to change this to
//i'm looking at changing the original data to look like this. The Team will have a position on the array, for example array[0][1](this column will be taken by all values that belong to team 'D PG') and array[0][2](will be taken by all values that belong to the team 'D PP')
// you will notice that all the other values for other months are at zero, thats because i want the initial values to be zero untill data has been put in for them
[
[
"January",
194,
143,
19,
3,
2,
2
],
[
"February",
35,
120,
40,
30,
9,
6
],
[
"March",
0,
0,
0,
0,
0,
0
],
[
"April",
0,
0,
0,
0,
0,
0
],
[
"May",
0,
0,
0,
0,
0,
0
],
[
"June",
0,
0,
0,
0,
0,
0
],
[
"July",
0,
0,
0,
0,
0,
0
],
[
"August",
0,
0,
0,
0,
0,
0
],
[
"September",
0,
0,
0,
0,
0,
0
],
[
"October",
0,
0,
0,
0,
0,
0
],
[
"November",
0,
0,
0,
0,
0,
0
],
[
"December",
0,
0,
0,
0,
0,
0
]
]
i use a for Loop to iterate the original Data object and then use if statements to group them by Month and Team. But the code will become very bulky and i believe inefficient. Any ideas on a better way to do this
var grouped = eval('[["January",0,0,0,0,0,0],["February",0,0,0,0,0,0],["March"0,0,0,0,0,0],["April",0,0,0,0,0,0],["May",0,0,0,0,0,0],["June"0,0,0,0,0,0],["July",0,0,0,0,0,0],["August",0,0,0,0,0,0],["September",0,0,0,0,0,0],["October",0,0,0,0,0,0],["November",0,0,0,0,0,0],["December",0,0,0,0,0,0]]');
for (i=0; i< dataResult.length; i++) {
if((dataResult[i]['Month'] == 'January') && (dataResult[i]['Team'] == 'D PG')){
var original = dataResult[i]['Original_x0020_Size_x0020__x0028'];
grouped[0][1] =original;
}
if((dataResult[i]['Month'] == 'January') && (dataResult[i]['Team'] == 'D PP')){
var original = dataResult[i]['Original_x0020_Size_x0020__x0028'];
grouped[0][2] =original;
}
if((dataResult[i]['Month'] == 'January') && (dataResult[i]['Team'] == 'D RE')){
var original = dataResult[i]['Original_x0020_Size_x0020__x0028'];
grouped[0][3] =original;
}
if((dataResult[i]['Month'] == 'January') && (dataResult[i]['Team'] == 'D GP')){
var original = dataResult[i]['Original_x0020_Size_x0020__x0028'];
grouped[0][4] =original;
}
if((dataResult[i]['Month'] == 'January') && (dataResult[i]['Team'] == 'D PC')){
var original = dataResult[i]['Original_x0020_Size_x0020__x0028'];
grouped[0][5] =original;
}
if((dataResult[i]['Month'] == 'January') && (dataResult[i]['Team'] == 'D PT')){
var original = dataResult[i]['Original_x0020_Size_x0020__x0028'];
grouped[0][6] =original;
}
As always, just use a hashtable to easify things:
const result = [], month = {};
// I did not want to put that identifier everywhere... :/
const wtf = "Original_x0020_Size_x0020__x0028";
for(const entry of data){
if(month[entry.Month]){
month[entry.Month].push(entry[wtf]);
} else {
result.push(month[entry.Month] = [entry.Month, entry[wtf]]);
}
}
I'm trying to follow the docs on how to add a trending line on my serial type bar graph.
AmCharts.makeChart('chartdiv', {
type: 'serial',
addClassNames: true,
theme: 'light',
dataProvider: data,
startDuration: 1,
categoryField: 'month',
graphs: [
{
valueField: 'complaints',
type: 'column',
fillAlphas: 0.8,
balloonText: "# of complaints on [[category]]: <b>[[value]]</b>"
},
{
valueField: 'expectation',
type: 'line',
// bullet: 'round',
lineColor: 'green',
balloonText: "Expected less than <b>[[value]]</b> for [[category]]",
dashLengthField: "dashLengthLine"
}
],
categoryAxis: {
autoGridCount: false,
gridCount: data.length,
gridPosition: "start",
// labelRotation: 90
},
export: {
enabled: true
},
trendLines: [{
initialValue: 6,
finalValue: 8
}]
});
The trendingLines is not doing much there. I've tried in many ways to declare it, but no luck. Here's some of the data I'm working with:
[{
"expectation": 2,
"tendValue": 1,
"month": "January",
"complaints": 1
}, {
"expectation": 2,
"month": "February",
"complaints": 2
}, {
"expectation": 2,
"month": "March",
"complaints": 0
}, {
"expectation": 2,
"month": "April",
"complaints": 1
}, {
"expectation": 2,
"month": "May",
"complaints": 0
}, {
"expectation": 2,
"month": "June",
"complaints": 1
}, {
"expectation": 2,
"month": "July",
"complaints": 2
}, {
"expectation": 2,
"month": "August ",
"complaints": 1
}, {
"expectation": 2,
"month": "September",
"complaints": 3
}, {
"expectation": 2,
"month": "October",
"complaints": 1
}, {
"expectation": 2,
"month": "November",
"complaints": 2
}, {
"expectation": 2,
"tendValue": 3,
"month": "December",
"complaints": 3
} ]
What you're missing out is the declaration of a start and an end point. You only tell the trendline its values.
Minimum code for a trendline should be sth. like this:
{
"finalDate": "2012-01-22 12",
"finalValue": 10,
"initialDate": "2012-01-17 12",
"initialValue": 16
}
or in your case using initialCategory and finalCategory. Take a look at the class reference for more info on trendline parameters or look at this nice little demo.
Take the array of objects below "toursByHotels" — I want to take this data and get the sum of tours for each object that has the same name (the hotel's name, ie. Marriott, etc).
Is there an easier way in d3 than having to create 5 new arrays with the same names, then sum the tours of those?
var toursByHotel = [
{
"name": "Marriott",
"month": 1,
"tours": 10
},
{
"name": "Marriott",
"month": 2,
"tours": 15
},
{
"name": "Marriott",
"month": 3,
"tours": 8
},
{
"name": "Marriott",
"month": 4,
"tours": 12
},
{
"name": "Marriott",
"month": 5,
"tours": 18
},
{
"name": "Marriott",
"month": 6,
"tours": 25
},
{
"name": "Marriott",
"month": 7,
"tours": 40
},
{
"name": "Marriott",
"month": 8,
"tours": 33
},
{
"name": "Marriott",
"month": 9,
"tours": 25
},
{
"name": "Marriott",
"month": 10,
"tours": 21
},
{
"name": "Marriott",
"month": 11,
"tours": 18
},
{
"name": "Marriott",
"month": 12,
"tours": 14
},
{
"name": "Springhill",
"month": 1,
"tours": 10
},
{
"name": "Springhill",
"month": 2,
"tours": 15
},
{
"name": "Springhill",
"month": 3,
"tours": 8
},
{
"name": "Springhill",
"month": 4,
"tours": 12
},
{
"name": "Springhill",
"month": 5,
"tours": 18
},
{
"name": "Springhill",
"month": 6,
"tours": 25
},
{
"name": "Springhill",
"month": 7,
"tours": 40
},
{
"name": "Springhill",
"month": 8,
"tours": 33
},
{
"name": "Springhill",
"month": 9,
"tours": 25
},
{
"name": "Springhill",
"month": 10,
"tours": 21
},
{
"name": "Springhill",
"month": 11,
"tours": 18
},
{
"name": "Springhill",
"month": 12,
"tours": 14
},
{
"name": "Residence",
"month": 1,
"tours": 10
},
{
"name": "Residence",
"month": 2,
"tours": 15
},
{
"name": "Residence",
"month": 3,
"tours": 8
},
{
"name": "Residence",
"month": 4,
"tours": 12
},
{
"name": "Residence",
"month": 5,
"tours": 18
},
{
"name": "Residence",
"month": 6,
"tours": 25
},
{
"name": "Residence",
"month": 7,
"tours": 40
},
{
"name": "Residence",
"month": 8,
"tours": 33
},
{
"name": "Residence",
"month": 9,
"tours": 25
},
{
"name": "Residence",
"month": 10,
"tours": 21
},
{
"name": "Residence",
"month": 11,
"tours": 18
},
{
"name": "Residence",
"month": 12,
"tours": 14
},
{
"name": "Courtyard",
"month": 1,
"tours": 10
},
{
"name": "Courtyard",
"month": 2,
"tours": 15
},
{
"name": "Courtyard",
"month": 3,
"tours": 8
},
{
"name": "Courtyard",
"month": 4,
"tours": 12
},
{
"name": "Courtyard",
"month": 5,
"tours": 18
},
{
"name": "Courtyard",
"month": 6,
"tours": 25
},
{
"name": "Courtyard",
"month": 7,
"tours": 40
},
{
"name": "Courtyard",
"month": 8,
"tours": 33
},
{
"name": "Courtyard",
"month": 9,
"tours": 25
},
{
"name": "Courtyard",
"month": 10,
"tours": 21
},
{
"name": "Courtyard",
"month": 11,
"tours": 18
},
{
"name": "Courtyard",
"month": 12,
"tours": 14
},
{
"name": "Renaissance",
"month": 1,
"tours": 10
},
{
"name": "Renaissance",
"month": 2,
"tours": 15
},
{
"name": "Renaissance",
"month": 3,
"tours": 8
},
{
"name": "Renaissance",
"month": 4,
"tours": 12
},
{
"name": "Renaissance",
"month": 5,
"tours": 18
},
{
"name": "Renaissance",
"month": 6,
"tours": 25
},
{
"name": "Renaissance",
"month": 7,
"tours": 40
},
{
"name": "Renaissance",
"month": 8,
"tours": 33
},
{
"name": "Renaissance",
"month": 9,
"tours": 25
},
{
"name": "Renaissance",
"month": 10,
"tours": 21
},
{
"name": "Renaissance",
"month": 11,
"tours": 18
},
{
"name": "Renaissance",
"month": 12,
"tours": 14
}
];
You can use reduce and return object where each key is hotel name and value is sum of tours. DEMO
data = data.reduce(function(obj, e) {
obj[e.name] = (obj[e.name] || 0) + e.tours;
return obj;
}, {});
console.log(data)
If you want to get sum and percentage for each hotel you can do it like this DEMO
var result = {}
var total = data.reduce((a, b) => {return a + b.tours }, 0);
data.forEach(function(e) {
if(!this[e.name]) {
this[e.name] = {sum: e.tours, percentage: 0}
result[e.name] = this[e.name];
}
this[e.name].sum += e.tours;
this[e.name].percentage = (this[e.name].sum / total)*100;
}, {});
console.log(result)
Using reduce would be the best way to do this:
Working Example
// lets keep track of the total here:
var total = 0;
var totals = a.reduce(function(curr, next) {
curr[next.name] = (curr[next.name] || 0) + next.tours;
// increment total here:
total += next.tours;
return curr;
}, {});
for (var hotel in totals) {
var obj = {};
obj.name = totals[hotel];
obj.percentage = (totals[hotel] / total) * 100 + '%';
totals[hotel] = obj;
}
MDN docs on .reduce
I have a JSON like below
var data = [
{ "year": 2013, "month": 10, "week": 41, "changes": 1590 },
{ "year": 2013, "month": 10, "week": 42, "changes": 0 },
{ "year": 2013, "month": 10, "week": 43, "changes": 2008 },
{ "year": 2013, "month": 10, "week": 44, "changes": 3900 },
{ "year": 2014, "month": 10, "week": 41, "changes": 1052 },
{ "year": 2014, "month": 10, "week": 42, "changes": 0 },
{ "year": 2014, "month": 10, "week": 43, "changes": 10122 },
{ "year": 2014, "month": 10, "week": 44, "changes": 1461 },
{ "year": 2015, "month": 10, "week": 41, "changes": 682 },
{ "year": 2015, "month": 10, "week": 42, "changes": 0 },
{ "year": 2015, "month": 10, "week": 43, "changes": 244 },
{ "year": 2015, "month": 10, "week": 44, "changes": 21 }
];
and i want to generate this JSON some thing like that
var firstYear = "2013";
var secondYear = "2014";
var thildYear = "2015";
var sampleData = [
{ "week": 41, "firstYear": 1590, "secondYear": 1052, "thildYear": 682 },
{ "week": 42, "firstYear": 0, "secondYear": 0, "thildYear": 0 },
{ "week": 43, "firstYear": 2008, "secondYear": 10122, "thildYear": 244 },
{ "week": 44, "firstYear": 858, "secondYear": 1461, "thildYear": 21 }
];
i write a code but it does't work
var jsonObjdata = [];
var yearExist = "";
var weekExist = "";
var SampleRequestBody = {};
$.each(data, function (key, value) {
if (value.year != yearExist) {
SampleRequestBody.week = value.week;
SampleRequestBody.firstYear = value.changes;
yearExist = value.year;
}
else if (value.year == yearExist && value.week == weekExist + 1) {
SampleRequestBody.secondYear = value.changes;
}
else if (value.year == yearExist && value.week == weekExist + 1) {
SampleRequestBody.thildYear = value.changes;
jsonObjdata.push(SampleRequestBody);
}
});
Can you please help me ?
Here is another take at it using array.prototype.reduce:
var weeks = [], flatData;
flatData = data.reduce(function(outData, obj) {
var tmp = {}, prop = 'year' + obj.year;
if ((idx = weeks.indexOf(obj.week)) >= 0) {
outData[idx][prop] = obj.changes;
} else {
weeks.push(obj.week);
tmp['week'] = obj.week;
tmp[prop] = obj.changes;
outData.push(tmp);
}
return outData;
}, []);
It will return you an object array like this:
week year2013 year2014 year2015
---- -------- -------- --------
41 1590 1052 682
42 0 0 0
43 2008 10122 244
44 3900 1461 21
Demo Fiddle: http://jsfiddle.net/abhitalks/kLg5f1wk/
(check console)
Demo Snippet:
(check console)
var data = [
{ "year": 2013, "month": 10, "week": 41, "changes": 1590 },
{ "year": 2013, "month": 10, "week": 42, "changes": 0 },
{ "year": 2013, "month": 10, "week": 43, "changes": 2008 },
{ "year": 2013, "month": 10, "week": 44, "changes": 3900 },
{ "year": 2014, "month": 10, "week": 41, "changes": 1052 },
{ "year": 2014, "month": 10, "week": 42, "changes": 0 },
{ "year": 2014, "month": 10, "week": 43, "changes": 10122 },
{ "year": 2014, "month": 10, "week": 44, "changes": 1461 },
{ "year": 2015, "month": 10, "week": 41, "changes": 682 },
{ "year": 2015, "month": 10, "week": 42, "changes": 0 },
{ "year": 2015, "month": 10, "week": 43, "changes": 244 },
{ "year": 2015, "month": 10, "week": 44, "changes": 21 }
], weeks = [], flatData;
flatData = data.reduce(function(outData, obj) {
var tmp = {}, prop = 'year' + obj.year;
if ((idx = weeks.indexOf(obj.week)) >= 0) {
outData[idx][prop] = obj.changes;
} else {
weeks.push(obj.week);
tmp['week'] = obj.week;
tmp[prop] = obj.changes;
outData.push(tmp);
}
return outData;
}, []);
console.table(flatData);
I suggest to use Array.prototype.forEach and Array.prototype.map for creating a temporary object and the later result array.
var data = [{ "year": 2013, "month": 10, "week": 41, "changes": 1590 }, { "year": 2013, "month": 10, "week": 42, "changes": 0 }, { "year": 2013, "month": 10, "week": 43, "changes": 2008 }, { "year": 2013, "month": 10, "week": 44, "changes": 3900 }, { "year": 2014, "month": 10, "week": 41, "changes": 1052 }, { "year": 2014, "month": 10, "week": 42, "changes": 0 }, { "year": 2014, "month": 10, "week": 43, "changes": 10122 }, { "year": 2014, "month": 10, "week": 44, "changes": 1461 }, { "year": 2015, "month": 10, "week": 41, "changes": 682 }, { "year": 2015, "month": 10, "week": 42, "changes": 0 }, { "year": 2015, "month": 10, "week": 43, "changes": 244 }, { "year": 2015, "month": 10, "week": 44, "changes": 21 }],
groups = { '2013': 'firstYear', '2014': 'secondYear', '2015': 'thirdYear' },
temp = {},
result;
data.forEach(function (a) {
temp[a.week] = temp[a.week] || { week: a.week };
temp[a.week][groups[a.year]] = a.changes;
});
result = Object.keys(temp).map(function (k) { return temp[k]; });
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Instead of debugging your code I think a more "algorithmic" approach would be better. Consider this :
function processWeek(week) {
var weekItem = { week: week };
data.forEach(function(item) {
if (item.week == week) switch (item.year) {
case firstYear : weekItem.firstYear = item.changes; break;
case secondYear : weekItem.secondYear = item.changes; break;
case thildYear : weekItem.thildYear = item.changes; break;
default : alert('this will never happen'); break;
}
})
return weekItem;
}
for (var week=41;week<45;week++) {
sampleData.push(processWeek(week));
}
The above produces the desired result -> http://jsfiddle.net/by22q6h8/
The idea is to narrow down the construct of new items to simple steps :
create the item
isolate weeks we are after
determine which changes go to which new attribute.