[英]Fastest way to gather JS objects by date
我的银行交易数据格式如下:
var transactions = {
food: [
{
date: new Date('2016-01-09'),
amount: 123.45
},
{
date: new Date('2016-01-16'),
amount: 87.88
},
{
date: new Date('2016-01-23'),
amount: 99.99
},
{
date: new Date('2016-01-30'),
amount: 99.99
}
],
doctor: [
{
date: new Date('2016-01-15'),
amount: 1124.01
},
{
date: new Date('2016-01-16'),
amount: 656.00
},
{
date: new Date('2016-01-23'),
amount: 1000.00
},
]
}
也就是说,看起来像{transaction_type: [array of transactions]}
。
我想按日期对这些交易进行分组,最后我得到
var aligned_transactions = [
{
date: new Date('2016-01-09'),
amounts: [123.45]
},
{
date: new Date('2016-01-15'),
amounts: [1124.01]
},
{
date: new Date('2016-01-16'),
amounts: [87.88, 656.00]
},
{
date: new Date('2016-01-23'),
amounts: [99.99, 1000.00]
},
{
date: new Date('2016-01-30'),
amounts: [99.99]
}
]
因此,现在按日期将金额分组。 当然,在实际情况下,有数百种交易类型,每种交易类型都包含成千上万笔交易(大约要处理一百万笔交易)。 以这种方式转换交易的“最快”方法是什么? 在这里,最快意味着总花费时间进行转换。 jsperf的结果会很棒。
请注意,我已经尝试了几种方法,但发现嵌套循环的“显而易见”方法非常慢:在我的计算机上,大约有12秒钟,总事务数为100万(Chrome,Ubuntu)。 我猜测创建所有这些新对象会付出巨大的代价。
一种颇有希望的方法是“垂直”切片这些事务列表,以便获得一堆小数组,然后从中创建对象,然后将它们递归“合并”在一起。 这是非常快的,在我的机器上完成上述100万笔交易大约需要6秒。 不过,我希望有一种更快的方法。
编辑:
这是嵌套的for循环解决方案:
function align_data(transaction_types) {
var i, j, transaction, transactions;
var timestamps = {};
for (i = 0; i < transaction_types.length; i++) {
transactions = transaction_types[i];
for (j = 0; j < transactions.length; j++) {
transaction = transactions[j];
if (timestamps[transaction.date]) {
timestamps[transaction.date].amounts.push(transaction.amount);
} else {
timestamps[transaction.date] = {
date: transaction.date,
amounts: [transaction.amount]
};
}
}
}
var aligned = [];
for (date in timestamps) {
if (timestamps.hasOwnProperty(date)) {
aligned.push(timestamps[date]);
}
}
return aligned;
}
我刚刚对其进行了测试,在我的计算机上随机执行一百万条记录时,运行您的代码大约需要5到6秒钟,而以下代码可能需要半秒钟:
function align_data(transaction_types) {
var i, j, transaction, transactions;
var timestamps = {};
for (i = 0; i < transaction_types.length; i++) {
transactions = transaction_types[i];
for (j = 0; j < transactions.length; j++) {
transaction = transactions[j];
if (timestamps[transaction.date.getTime()]) {
timestamps[transaction.date.getTime()].amounts.push(transaction.amount);
} else {
timestamps[transaction.date.getTime()] = {
date: transaction.date,
amounts: [transaction.amount]
};
}
}
}
var aligned = [];
for (date in timestamps) {
if (timestamps.hasOwnProperty(date)) {
aligned.push(timestamps[date]);
}
}
return aligned;
}
我所做的只是通过transaction.date.getTime()
而不是transaction.date
为timestamps
编制索引。
我认为这是一种情况,您确实应该尝试使用WebWorkers。
如何在所有记录中使用单个累加器对象,然后将其转换为首选数组格式:
function align_data(transactions) {
var acc = {};
var d;
for (var key in transactions) {
transactions[key].forEach(function (record) {
d = record.date.toISOString();
if (d in acc) {
acc[d].push(record.amount);
} else {
acc[d] = [record.amount];
}
});
}
var aligned_transactions = [];
for (var date in acc) {
aligned_transactions.push({date: new Date(date), amounts: acc[date]});
}
return aligned_transactions;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.