#node.js
#node.js
Вопрос:
В восходящем потоке я поддерживаю высокочастотный вызов API. После вызова у меня будет большой массив объектов, которые мне нужно эффективно суммировать (добавить) в итоговые значения для каждого объекта как можно быстрее, используя nodejs.
Я уверен, что мог бы сделать это с помощью нескольких функций цикла, но хотел посмотреть, смогут ли умные люди здесь найти более эффективный способ.
[{
samplefield1: 123,
samplefield2: 345,
samplefield3: 678,
samplefield4: 910,
samplefield5: 111
},
{
samplefield1: 123,
samplefield2: 345,
samplefield3: 678,
samplefield4: 910,
samplefield5: 111
},
{
samplefield1: 123,
samplefield2: 345,
samplefield3: 678,
samplefield4: 910,
samplefield5: 111
},
{
samplefield1: 123,
samplefield2: 345,
samplefield3: 678,
samplefield4: 910,
samplefield5: 111
}....
]
желаемый результат
{
samplefield1total: 1349596065934,
samplefield2total: 5856960650505,
samplefield3total: 4344343434343,
samplefield4total: 44444434342910,
samplefield5total: 79797696969696
}
В качестве дополнительного бонуса было бы удивительно, если бы я мог также получить количество всех записей из входных данных, добавленных в массив, как показано ниже…
вывод бонусного задания:
{
samplefield1total: 1349596065934,
samplefield2total: 5856960650505,
samplefield3total: 4344343434343,
samplefield4total: 44444434342910,
samplefield5total: 79797696969696,
recordcount: 145634
}
но если это не очень эффективно сделать в приведенном выше примере, я могу сделать это снаружи с помощью простого оператора array.length
ценю любую помощь, которую вы можете предложить
Комментарии:
1. Любая операция с большими данными заблокирует цикл событий, возможно, попробуйте рабочие потоки 🙂
2. Гарантируется ли, что каждый объект в большом массиве имеет одинаковые ключи?
3. да, все идентификаторы ключевых полей будут одинаковыми в каждом JSON внутри массива
4. @MattNicholls пожалуйста, не говорите мне, что вы на самом деле получаете все это в формате JSON (в виде огромной строки)
5. Эй, ваш сценарий не совсем понятен. Что посылает вам ваш высокочастотный вызов? новые элементы для этого массива? Вы храните этот массив в памяти или используете какую-то базу данных? Я имею в виду, что самое простое, что я могу придумать, это просто сохранить
sums
объект с ранее рассчитанными суммами и просто добавлять новые значения по мере их получения, но я не уверен, что это реальный сценарий.
Ответ №1:
Лучшее, что вы можете сделать, это не использовать помощники массива (которые должны выделять фрейм вызова для каждого отдельного экземпляра простого добавления). Простой цикл for — это все, что вам нужно, поэтому вам все равно нужно получить длину массива.
const data = [{samplefield1: 123, samplefield2: 345, samplefield3: 678, samplefield4: 910, samplefield5: 111},{samplefield1: 123, samplefield2: 345, samplefield3: 678, samplefield4: 910, samplefield5: 111},{samplefield1: 123, samplefield2: 345, samplefield3: 678, samplefield4: 910, samplefield5: 111},{samplefield1: 123, samplefield2: 345, samplefield3: 678, samplefield4: 910, samplefield5: 111}];
let totals = data[0];
let recordcount = data.length;
let keys = Object.keys(totals);
let keycount = keys.length;
for(let i = 1; i < recordcount; i ) {
for(let j = 0; j < keycount; j ) {
totals[keys[j]] = data[i][keys[j]];
}
}
totals.recordcount = recordcount;
console.log(totals);
К сожалению, вам не удастся избежать этой O(N*M)
временной сложности, поскольку требуется получить доступ к каждому из M полей для N объектов, чтобы добавить их.
Как отмечено в комментариях @Shubh, это заблокирует цикл событий. Если это высокочастотный вызов API, каждый вызов которого требует такого большого объема обработки, вам следует передать его в рабочий поток. Если возможно, подумайте, откуда вы получаете данные (это база данных?) и посмотрите, можете ли вы заставить ее выполнять вычисления вместо этого.
Обратите внимание, что если ваши числа будут намного больше, чем ваши данные выборки в post, возможно, вам придется использовать вместо этого BigInts для сумм, поскольку JavaScript обеспечивает такую точность только в своем числовом типе.
Комментарии:
1. хороший отзыв о bigint, я не рассматривал это, но это определенно было бы применимо к некоторым полям. кроме того, я рад, что отказался от этого бонусного задания, поскольку я бы пропустил то, что оно уже записано в разработанном вами цикле. Эти данные поступают непосредственно из dynamodb, поэтому я не верю, что есть возможность заставить его обрабатывать вычисления.
2. есть ли возможность сэкономить время, вычисляя итоговые значения для каждого поля параллельно?
3. @MattNicholls Вы не сможете распараллелить синхронные вычисления, если не поместите каждое поле в отдельный рабочий поток, поскольку JavaScript однопоточный. Я думаю, это вариант, если вы готовы использовать его, но он может потребовать больших затрат памяти, поскольку копия данных должна быть отправлена каждому рабочему.