繁体   English   中英

按日期收集JS对象的最快方法

[英]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.datetimestamps编制索引。

我认为这是一种情况,您确实应该尝试使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM