我的银行交易数据格式如下:
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]
}
]
因此,金额现在按日期分组。当然,在实际设置中,有几百种事务类型,每种类型都有数千个事务的数组(大约需要处理100万个事务)。以这种方式转换交易的“最快”方式是什么?这里,最快意味着完成转换所花费的总时间。一个jsperf结果会很棒。
请注意,我已经尝试了几种方法,并且发现嵌套for循环的“明显”方法非常慢:我的机器上有大约12秒,总交易量为100万(Chrome,Ubuntu)。我猜测创建所有这些新对象正在造成损失。
一种有前途的方法是“垂直”切片这些事务列表,这样我就得到了一堆小数组,然后我从中创建对象,并递归地将它们“合并”在一起。这非常快,在我的机器上大约6秒,上面有100万笔交易。不过,我希望有更快的方式。
编辑:
这是嵌套的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;
}
答案 0 :(得分:1)
我刚刚对它进行了测试,在我的计算机上随机设置了100万条记录,运行代码大约需要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;
}
我所做的更改是按timestamps
而不是transaction.date.getTime()
索引transaction.date
。
答案 1 :(得分:0)
我认为这是一种情况,当你真的应该尝试使用时 WebWorkers.
答案 2 :(得分:0)
如何在所有记录中使用单个累加器对象,然后将其转换为首选数组格式:
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;
}