Свернуть массив обьектов JS
Гайз, помогите, пожалуйста красиво свернуть массив объектов.
Логика такая - объекту, который приходит без id (будет один такой) нужно добавить в его
features[<вложенный объект с name=="HEAD">].value
значения из другого объекта: с тем-же типом (тоже будет один), но у которого есть id.
Я написал, но я не знаю на сколько мой вариант оптимальный с точки зрения производительности. Понимаю, что можно reduce применить, но что-то не очень получается. Спасибо!!
let orders = [
{
type: "NEW",
features: [
{ value: ['aa', 'bb'], name: "URL" },
{ value: ['cc', 'dd'], name: "HEAD" }
]
}, {
id: "10",
type: "NEW",
features: [
{ value: ['ee', 'ff'], name: "URL" },
{ value: ['gg', 'hh'], name: "HEAD" }
]
}, {
id: "23",
type: "OLD",
features: [
{ value: ['ii', 'gg'], name: "URL" },
{ value: ['kk', 'll'], name: "HEAD" }
]
}, {
id: "55",
type: "OLD",
features: [
{ value: ['mm', 'nn'], name: "URL" },
{ value: ['oo', 'pp'], name: "HEAD" }
]
}
];
Мой вариант:
let orderWithNoid = orders.find(x => x.type === 'NEW' && !x.id);
let orderWithId = orders.find(x => x.type === 'NEW' && x.id);
const {
features: feat1
} = orderWithNoid;
const {
features: feat2
} = orderWithId;
for (let f1 of feat1) {
for (let f2 of feat2) {
if (f1.name === 'HEAD' && f1.name === f2.name) {
f1.value.push(...f2.value)
}
}
}
for (let order of orders) {
if (order.type === 'NEW' && !order.id) {
order.features = feat1;
}
}
Должна получиться такая структура:
let result = [{
type: "NEW",
features: [
{ value: ['aa', 'bb'], name: "URL" },
{
value: ["cc", "dd", "gg", "hh"] // добавились 2 последних значения
name: "HEAD"
}
]
}, {
id: "10",
type: "NEW",
features: [
{ value: ['ee', 'ff'], name: "URL" },
{ value: ['gg', 'hh'], name: "HEAD" }
]
}, {
id: "23",
type: "OLD",
features: [
{ value: ['ii', 'gg'], name: "URL" },
{ value: ['kk', 'll'], name: "HEAD" }
]
}, {
id: "55",
type: "OLD",
features: [
{ value: ['mm', 'nn'], name: "URL" },
{ value: ['oo', 'pp'], name: "HEAD" }
]
}
];
Ответы (1 шт):
const orders = getOrders(); // просто чтобы не скроллить вниз через литерал
// Подготовка. Тут в одном цикле выполняются две цели:
// 1. формируем словарь "типЗаказа:заказ" не заботясь о перезаписи ненужных нам типов
// (исходя из того условия задачи, что объект нужного типа всегда только один)
// 2. заодно ищем заказ без `id`, который предполагается тоже всего один
let orderWithNoId;
const ordersByType = orders.reduce((rslt, order) => {
if (!order.id)
orderWithNoId = order;
else
rslt[order.type] = order;
return rslt;
}, {});
// Далее поиск объектов feature:
// без цикла, практически мгновенно получаем заказ нужного нам типа и с `id`
const orderWithId = ordersByType[orderWithNoId.type],
// объявляем переиспользуемый коллбэк для поиска нужных нам `feature`
findHeadFeature = feat => feat.name === 'HEAD',
// тут два цикла, но коротких - в их оптимизации нет нужды
srcFeature = orderWithId.features.find(findHeadFeature),
dstFeature = orderWithNoId.features.find(findHeadFeature);
// И наконец, само копирование значений
dstFeature.value.push(...srcFeature.value);
console.log(orders);
function getOrders() {
return [
{
type: "NEW",
features: [
{ value: ['aa', 'bb'], name: "URL" },
{ value: ['cc', 'dd'], name: "HEAD" }
]
}, {
id: "10",
type: "NEW",
features: [
{ value: ['ee', 'ff'], name: "URL" },
{ value: ['gg', 'hh'], name: "HEAD" }
]
}, {
id: "23",
type: "OLD",
features: [
{ value: ['ii', 'gg'], name: "URL" },
{ value: ['kk', 'll'], name: "HEAD" }
]
}, {
id: "55",
type: "OLD",
features: [
{ value: ['mm', 'nn'], name: "URL" },
{ value: ['oo', 'pp'], name: "HEAD" }
]
}
];
}
я не знаю на сколько мой вариант оптимальный с точки зрения производительности
В примере вопроса, объем данных чрезвычайно мал (в массиве всего 4 объекта), и производительность с ним измерять бессмысленно, по-моему: практически любой код будет выполнять задачу настолько быстро, что разница между скоростью выполнения разных вариантов реализации будет близка к погрешности.
Если же говорить в общем и целом, то в первую очередь стоит избегать вложенности циклов (увеличения числа проходов), когда это возможно. Другие относительно дорогостоящие операции в JS, которые сами по себе не так уж "тормозят", но количество которых желательно сокращать внутри циклов: создание новых экземпляров объектов; вызовы; ветвления; поиск и замена с использованием сложных регулярок. Этот список конечно не полный, и в идеале, внутри циклов стоит выполнять как можно меньше любых операций: если что-то можно сделать вне цикла, то лучше так и поступать :)