首页 > 解决方案 > 在 JavaScript 中有效地填充对象数组中的值

问题描述

我有一个对象数组,例如:

a = [{"a":1,"b":2},{"a":3,"c":5}]

我想以一种有效的方式获得:

b = [{"a":1,"b":2,"c":"blabla"},{"a":3,"b":"blabla","c":5}]

到目前为止,我的功能是(在第一行使用underscoreJS库):

let fillFuncArr = (res,fill) => {
    // we fill the potential missing values
    let col_names = _.uniq(res.map(x => Object.keys(x)).reduce((acc, curr) => acc.concat(curr), []), false);
    for (let i = 0; i < res.length; i++) {
        for (let j = 0; j < col_names.length; j++) {
            if (!res[i].hasOwnProperty(col_names[j])) {
                res[i][col_names[j]] = fill;
            }
        }
    }
    return res;
};

在我上面的例子中,你会这样做:

b = fillFuncArr(a,"blabla")

如果可能的话,如何使该功能更快?

==================================================== ==========================

在回答基准回复后编辑:

我测试了这样的功能:

for (let i=0;i<num_tries;i++) {
    let time_tmp = performance.now();
    console.time("old");
    fillFuncArr(obj,"blah");
    console.timeEnd("old");
    time_old.push(performance.now()-time_tmp);
    time_tmp = performance.now();
    console.time("new");
    fillFuncArrNew(obj,"blah");
    console.timeEnd("new");
    time_new.push(performance.now()-time_tmp);
}

这个答案(旧函数的第一次计算总是比后续计算快得多,不太清楚为什么......)快了 50-100 倍。填充时间是相同的,它得到了构成所有速度增益的键:

 "old": [
        147.52006196975708,
        1065.4309248924255,
        1023.5124139785767,
        1021.830512046814,
        1855.5670911073685,
        1006.7114781141281,
        996.8541929721832,
        1306.3085260391235
    ],
    "new": [
        18.814231991767883,
        23.46549105644226,
        17.708116054534912,
        15.55942702293396,
        18.764864921569824,
        15.866382002830505,
        19.18179702758789,
        23.987511038780212
    ]

标签: javascriptperformance

解决方案


不知道这是否更快,但肯定更短:

dummy = {a: 'dummy', b: 'dummy', c: 'dummy'}

a = [{"a": 1, "b": 2}, {"a": 3, "c": 5}]

r = a.map(x => ({...dummy, ...x}))

console.log(r)

如果你想让假人完全动态,那么

function fillKeys(a, value) {
    let keys = new Set(a.flatMap(Object.keys)),
        dummy = Object.fromEntries(
            [...keys].map(k => [k, value]));
    return a.map(x => ({...dummy, ...x}));
}

//

a = [{"a": 1, "b": 2}, {"a": 3, "c": 5}]

r = fillKeys(a, 'dummy')

console.log(r)

话虽如此,我确信这实际上是一个 XY 问题,所以它有助于向我们解释你实际上在做什么。例如,如果您只希望列表中的所有对象都响应同一组键,那么使用代理会更容易(也更快)。


推荐阅读