使用 javascript reduce 方法将对象数组转换为每年和每月
convert array of objects to yearly and monthly using javascript reduce method
问题陈述:
我有一个对象数组,其中包含 month 、 sales 和 orders 作为属性。现在,我想创建一个如下所示的函数。可以根据参数提供结果。
function aggregate(json_data , yearly)
{
// This function could return an array of objects like following
// [ { Month : 2014 , Sales : x , Amount : x},
// { Month : 2015 , Sales : x , Amount : x }
// ]
};
如果用户将参数作为季度传递,则数据应按季度汇总
function aggregate(json_data , quarterly)
{
// This function could return an array of objects
// [ { Month : 2014Q1 , Sales : x , Amount : x},
// { Month : 2014Q2 , Sales : x , Amount : x }
// ............
// ............
// ]
}
示例数据
var data = [
{
Month: 201401,
Sales: 15,
Orders: 4
},
{
Month: 201402,
Sales: 12,
Orders: 3
},
{
Month: 201403,
Sales : 16,
Orders: 5
},
{
Month: 201404,
Sales: 12,
Orders: 2
},
{
Month: 201405,
Sales: 12,
Orders: 4
},
{
Month: 201406,
Sales: 10,
Orders: 3
},
{
Month: 201407,
Sales: 15,
Orders: 2
},
{
Month: 201408,
Sales: 14,
Orders: 3
},
{
Month: 201409,
Sales: 13,
Orders: 6
},
{
Month: 201410,
Sales: 13,
Orders: 5
},
{
Month: 201411,
Sales: 12,
Orders: 2
},
{
Month: 201412,
Sales: 11,
Orders: 4
},
{
Month: 201501,
Sales: 15,
Orders: 4
},
{
Month: 201502,
Sales: 12,
Orders: 6
},
{
Month: 201503,
Sales : 6,
Orders: 5
},
{
Month: 201504,
Sales: 10,
Orders: 11
},
{
Month: 201505,
Sales: 10,
Orders: 2
},
{
Month: 201506,
Sales: 10,
Orders: 3
},
{
Month: 201507,
Sales: 10,
Orders: 1
},
{
Month: 201508,
Sales: 10,
Orders: 4
},
{
Month: 201509,
Sales: 10,
Orders: 2
},
{
Month: 201510,
Sales: 10,
Orders: 3
},
{
Month: 201511,
Sales: 10,
Orders: 2
},
{
Month: 201512,
Sales: 10,
Orders: 1
}
];
求指教,如果有其他建议要么适配问题。
有人提出这是一个重复的问题。但是,我正在使用日期对象。 (建议前请检查重复项link)
您可以使用散列 table 并根据所需的年度或季度数据聚合使用密钥。
此提案使用 Month
作为字符串。
function aggregate(array, quarterly) {
var hash = Object.create(null),
result = [];
data.forEach(function (o) {
var [period, month] = o.Month.toString().split(/(?=..$)/);
if (quarterly) {
period += 'Q' + Math.floor((+month + 2) / 3);
}
if (!hash[period]) {
hash[period] = { period, Sales: 0, Orders: 0 };
result.push(hash[period]);
}
hash[period].Sales += o.Sales;
hash[period].Orders += o.Orders;
});
return result;
}
var data = [{ Month: 201401, Sales: 15, Orders: 4 }, { Month: 201402, Sales: 12, Orders: 3 }, { Month: 201403, Sales: 16, Orders: 5 }, { Month: 201404, Sales: 12, Orders: 2 }, { Month: 201405, Sales: 12, Orders: 4 }, { Month: 201406, Sales: 10, Orders: 3 }, { Month: 201407, Sales: 15, Orders: 2 }, { Month: 201408, Sales: 14, Orders: 3 }, { Month: 201409, Sales: 13, Orders: 6 }, { Month: 201410, Sales: 13, Orders: 5 }, { Month: 201411, Sales: 12, Orders: 2 }, { Month: 201412, Sales: 11, Orders: 4 }, { Month: 201501, Sales: 15, Orders: 4 }, { Month: 201502, Sales: 12, Orders: 6 }, { Month: 201503, Sales: 6, Orders: 5 }, { Month: 201504, Sales: 10, Orders: 11 }, { Month: 201505, Sales: 10, Orders: 2 }, { Month: 201506, Sales: 10, Orders: 3 }, { Month: 201507, Sales: 10, Orders: 1 }, { Month: 201508, Sales: 10, Orders: 4 }, { Month: 201509, Sales: 10, Orders: 2 }, { Month: 201510, Sales: 10, Orders: 3 }, { Month: 201511, Sales: 10, Orders: 2 }, { Month: 201512, Sales: 10, Orders: 1 }];
console.log(aggregate(data));
console.log(aggregate(data, true));
.as-console-wrapper { max-height: 100% !important; top: 0; }
不完全确定这是否是同一个问题,但我最近不得不解决一个看起来至少非常相似的问题。我有一组带有日期和值的对象,例如:
statsData = [
{ x: randomDate, y: 1 },
{ x: randomDate, y: 2 },
{ x: randomDate, y: 1 },
{ x: randomDate, y: 4 },
{ x: randomDate, y: 3 },
{ x: randomDate, y: 2 },
{ x: randomDate, y: 1 },
{ x: randomDate, y: 4 },
{ x: randomDate, y: 6 },
{ x: randomDate, y: 5 },
{ x: randomDate, y: 1 }
]
而且我需要减少它,以便将具有同一月份的所有对象组合在一个对象下,该对象将那个月的所有值相加。
我所做的是,首先对它们进行排序,以防它们不按时间顺序排列:
sortData(data) {
return data.sort((a, b) => {
return +a.x - +b.x;
});
}
然后使用这个reduce函数:
reduceByMonth(data) {
if (data) {
return data.reduce((total, current, index) => {
const month = { x: null, y: 0 };
if (index !== 0 && (total && total[total.length - 1] && total[total.length - 1].x && monthsMatch(total[total.length - 1].x, current.x))) {
total[total.length - 1].y = total[total.length - 1].y + current.y;
return total;
} else {
month.x = new Date(current.x.getFullYear(), current.x.getMonth());
month.y = month.y + current.y;
total.push(month);
return total;
}
}, []);
} else {
console.error('Cannot reduce undefined data');
return []
}
}
函数 monthsMatch 只是检查两个日期的月份是否匹配:
monthsMatch(dateA, dateB) {
if (dateA.getFullYear() === dateB.getFullYear()) {
return dateA.getMonth() === dateB.getMonth();
} else {
return false;
}
}
问题陈述:
我有一个对象数组,其中包含 month 、 sales 和 orders 作为属性。现在,我想创建一个如下所示的函数。可以根据参数提供结果。
function aggregate(json_data , yearly)
{
// This function could return an array of objects like following
// [ { Month : 2014 , Sales : x , Amount : x},
// { Month : 2015 , Sales : x , Amount : x }
// ]
};
如果用户将参数作为季度传递,则数据应按季度汇总
function aggregate(json_data , quarterly)
{
// This function could return an array of objects
// [ { Month : 2014Q1 , Sales : x , Amount : x},
// { Month : 2014Q2 , Sales : x , Amount : x }
// ............
// ............
// ]
}
示例数据
var data = [
{
Month: 201401,
Sales: 15,
Orders: 4
},
{
Month: 201402,
Sales: 12,
Orders: 3
},
{
Month: 201403,
Sales : 16,
Orders: 5
},
{
Month: 201404,
Sales: 12,
Orders: 2
},
{
Month: 201405,
Sales: 12,
Orders: 4
},
{
Month: 201406,
Sales: 10,
Orders: 3
},
{
Month: 201407,
Sales: 15,
Orders: 2
},
{
Month: 201408,
Sales: 14,
Orders: 3
},
{
Month: 201409,
Sales: 13,
Orders: 6
},
{
Month: 201410,
Sales: 13,
Orders: 5
},
{
Month: 201411,
Sales: 12,
Orders: 2
},
{
Month: 201412,
Sales: 11,
Orders: 4
},
{
Month: 201501,
Sales: 15,
Orders: 4
},
{
Month: 201502,
Sales: 12,
Orders: 6
},
{
Month: 201503,
Sales : 6,
Orders: 5
},
{
Month: 201504,
Sales: 10,
Orders: 11
},
{
Month: 201505,
Sales: 10,
Orders: 2
},
{
Month: 201506,
Sales: 10,
Orders: 3
},
{
Month: 201507,
Sales: 10,
Orders: 1
},
{
Month: 201508,
Sales: 10,
Orders: 4
},
{
Month: 201509,
Sales: 10,
Orders: 2
},
{
Month: 201510,
Sales: 10,
Orders: 3
},
{
Month: 201511,
Sales: 10,
Orders: 2
},
{
Month: 201512,
Sales: 10,
Orders: 1
}
];
求指教,如果有其他建议要么适配问题。
有人提出这是一个重复的问题。但是,我正在使用日期对象。 (建议前请检查重复项link)
您可以使用散列 table 并根据所需的年度或季度数据聚合使用密钥。
此提案使用 Month
作为字符串。
function aggregate(array, quarterly) {
var hash = Object.create(null),
result = [];
data.forEach(function (o) {
var [period, month] = o.Month.toString().split(/(?=..$)/);
if (quarterly) {
period += 'Q' + Math.floor((+month + 2) / 3);
}
if (!hash[period]) {
hash[period] = { period, Sales: 0, Orders: 0 };
result.push(hash[period]);
}
hash[period].Sales += o.Sales;
hash[period].Orders += o.Orders;
});
return result;
}
var data = [{ Month: 201401, Sales: 15, Orders: 4 }, { Month: 201402, Sales: 12, Orders: 3 }, { Month: 201403, Sales: 16, Orders: 5 }, { Month: 201404, Sales: 12, Orders: 2 }, { Month: 201405, Sales: 12, Orders: 4 }, { Month: 201406, Sales: 10, Orders: 3 }, { Month: 201407, Sales: 15, Orders: 2 }, { Month: 201408, Sales: 14, Orders: 3 }, { Month: 201409, Sales: 13, Orders: 6 }, { Month: 201410, Sales: 13, Orders: 5 }, { Month: 201411, Sales: 12, Orders: 2 }, { Month: 201412, Sales: 11, Orders: 4 }, { Month: 201501, Sales: 15, Orders: 4 }, { Month: 201502, Sales: 12, Orders: 6 }, { Month: 201503, Sales: 6, Orders: 5 }, { Month: 201504, Sales: 10, Orders: 11 }, { Month: 201505, Sales: 10, Orders: 2 }, { Month: 201506, Sales: 10, Orders: 3 }, { Month: 201507, Sales: 10, Orders: 1 }, { Month: 201508, Sales: 10, Orders: 4 }, { Month: 201509, Sales: 10, Orders: 2 }, { Month: 201510, Sales: 10, Orders: 3 }, { Month: 201511, Sales: 10, Orders: 2 }, { Month: 201512, Sales: 10, Orders: 1 }];
console.log(aggregate(data));
console.log(aggregate(data, true));
.as-console-wrapper { max-height: 100% !important; top: 0; }
不完全确定这是否是同一个问题,但我最近不得不解决一个看起来至少非常相似的问题。我有一组带有日期和值的对象,例如:
statsData = [
{ x: randomDate, y: 1 },
{ x: randomDate, y: 2 },
{ x: randomDate, y: 1 },
{ x: randomDate, y: 4 },
{ x: randomDate, y: 3 },
{ x: randomDate, y: 2 },
{ x: randomDate, y: 1 },
{ x: randomDate, y: 4 },
{ x: randomDate, y: 6 },
{ x: randomDate, y: 5 },
{ x: randomDate, y: 1 }
]
而且我需要减少它,以便将具有同一月份的所有对象组合在一个对象下,该对象将那个月的所有值相加。
我所做的是,首先对它们进行排序,以防它们不按时间顺序排列:
sortData(data) {
return data.sort((a, b) => {
return +a.x - +b.x;
});
}
然后使用这个reduce函数:
reduceByMonth(data) {
if (data) {
return data.reduce((total, current, index) => {
const month = { x: null, y: 0 };
if (index !== 0 && (total && total[total.length - 1] && total[total.length - 1].x && monthsMatch(total[total.length - 1].x, current.x))) {
total[total.length - 1].y = total[total.length - 1].y + current.y;
return total;
} else {
month.x = new Date(current.x.getFullYear(), current.x.getMonth());
month.y = month.y + current.y;
total.push(month);
return total;
}
}, []);
} else {
console.error('Cannot reduce undefined data');
return []
}
}
函数 monthsMatch 只是检查两个日期的月份是否匹配:
monthsMatch(dateA, dateB) {
if (dateA.getFullYear() === dateB.getFullYear()) {
return dateA.getMonth() === dateB.getMonth();
} else {
return false;
}
}