Как лучше всего объединить вложенные массивы

У меня есть массив объектов, который выглядит так:

[
 {external_id: 1, items: [{k: 'v'}] },
 {external_id: 2, items: [{k1: 'v1'}] },
 {external_id: 1, items: [{k2: 'v2'}, {k3: 'v3'}] }
]

Что я хочу сделать, так это объединить вложенные массивы на основе external_id и вернуть «чистый массив», который будет выглядеть так:

[
 {external_id: 1, items: [{k: 'v'}, {k2: 'v2'}, {k3: 'v3'}] },
 {external_id: 2, items: [{k1: 'v1'}] }
]

Итак, мой вопрос: как это сделать без использования классического цикла for?

Какой длины массивы?

germanio 18.12.2020 18:41

Массивы не имели бы length >= 10

yury_hr 18.12.2020 18:44

Я настоятельно рекомендую вам прочитать документацию по массивам javascript: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… и основам работы с объектами: developer.mozilla.org/en-US. /docs/Learn/JavaScript/Objects/…

germanio 18.12.2020 18:48
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
Раскрытие чувствительных данных
Раскрытие чувствительных данных
Все внешние компоненты, рассмотренные здесь до сих пор, взаимодействуют с клиентской стороной. Однако, если они подвергаются атаке, они не...
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Руководство ChatGPT по продаже мини JS-файлов
Руководство ChatGPT по продаже мини JS-файлов
JS-файл - это файл, содержащий код JavaScript. JavaScript - это язык программирования, который в основном используется для добавления интерактивности...
1
3
66
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вам придется зацикливаться. Вы можете зацикливаться с помощью for, forEach, map, reduce, find, ... и т. д., но вам придется зацикливаться.

Вот способ, который создает карту с ключом external_id, а затем заполняет эту карту элементами. Наконец, значения этой карты представляют результат:

let data = [{external_id: 1, items: [{k: 'v'}] },{external_id: 2, items: [{k1: 'v1'}] },{external_id: 1, items: [{k2: 'v2'}, {k3: 'v3'}] }];

let map = new Map(data.map(({external_id}) => [external_id, { external_id, items:[] }]));
data.forEach(o => map.get(o.external_id).items.push(...o.items));
let result = [...map.values()];
console.info(result);

Использование сокращения и сортировки

let data = [{
    external_id: 1,
    items: [{
      k: 'v'
    }]
  },
  {
    external_id: 2,
    items: [{
      k1: 'v1'
    }]
  },
  {
    external_id: 1,
    items: [{
      k2: 'v2'
    }, {
      k3: 'v3'
    }]
  },
];

let ans = data
  .sort(function(a, b) {
    return a['external_id'] - b['external_id'];
  })
  .reduce((acc, currentObject) => {
    const endObject = acc[acc.length - 1];
    if (endObject && endObject['external_id'] === currentObject.external_id) {
      endObject.items.push(...currentObject.items);
    } else {
      acc.push({ ...currentObject
      });
    }
    return acc;
  }, []);
console.info(ans);

Спасибо, это тоже хорошее решение. Хотел бы я отметить оба ответа принятыми :)

yury_hr 18.12.2020 20:09

Использование другого объекта для группировки объектов с одним и тем же свойством external_id

let a = [
    {external_id: 1, items: [{k: 'v'}] },
    {external_id: 2, items: [{k1: 'v1'}] },
    {external_id: 1, items: [{k2: 'v2'}, {k3: 'v3'}] }
]

let obj = {};

a.forEach( ({external_id, items}) => {
    obj[external_id] ??= new Set;
    items.map( i => {
        obj[external_id].add(JSON.stringify(i));
    });
});

a = Object.keys(obj).map( (n) => {
    n = Number(n);
    return {
        external_id:n,
        items: [...obj[n]].map(JSON.parse)
    }
})

Другие вопросы по теме