Эффективно заполнять значения в массиве объектов в JavaScript - PullRequest
0 голосов
/ 21 ноября 2019

У меня есть массив объектов, таких как:

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")

Как сделать эту функцию быстрее, если это вообще возможно?

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

РЕДАКТИРОВАТЬ после ответов на контрольные ответы:

Iпроверил функции следующим образом:

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
    ]

Ответы [ 4 ]

2 голосов
/ 21 ноября 2019

Не знаю, быстрее ли это, но определенно короче:

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, поэтому она поможет объяснить нам, что вы на самом деле делаете. Например, если вы просто хотите, чтобы все объекты в списке реагировали на один и тот же набор ключей, это было бы намного проще (и также быстрее) с прокси.

1 голос
/ 21 ноября 2019

Сначала выясните все ключи в элементах массива, создайте объект «по умолчанию», заполненный fill в качестве его значений, затем выполните итерации по элементам и распределите объект по умолчанию, затем исходный объект:

const fillFuncArr = (arr, fill) => {
  const allKeys = new Set(arr.flatMap(Object.keys));
  const defaultObj = {};
  for (const key of allKeys) {
    defaultObj[key] = fill;
  }
  return arr.map(obj => ({ ...defaultObj, ...obj }));
};

a = [{"a":1,"b":2},{"a":3,"c":5}]
b = fillFuncArr(a,"blabla")
console.log(b);
0 голосов
/ 21 ноября 2019

const a = [{"a":1,"b":2},{"a":3,"c":5}];
const allKeys=[...new Set(a.flatMap(Object.keys))]
const dummyObj=Object.fromEntries(allKeys.map(key => [key, 'blabla']));
console.log(a.map(data => ({...dummyObj, ...data})))
0 голосов
/ 21 ноября 2019

Взгляните сюда:

console.time('allTest');
var was = [{a:1, b:2}, {a:3, c:5}];
function blah(array){
  var a = [], o, b = 'blabla';
  array.forEach(function(w){
    o = {};
    o.a = 'a' in w ? w.a : b;
    o.b = 'b' in w ? w.b : b;
    o.c = 'c' in w ? w.c : b;
    a.push(o);
  });
  return a;
}
console.time('test'); console.log(blah(was)); console.timeEnd('test'); console.timeEnd('allTest');

По крайней мере, это покажет вам, как проверить время.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...