Свернуть массив обьектов 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 шт):

Автор решения: yar85

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

→ Ссылка