Объединение объектов из массива с одинаковым значением ключа

#javascript #arrays #json

#javascript #массивы #json

Вопрос:

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

 var arr = [
    {id: 1, tech_id:11, action: 'swim'},
    {id: 2, tech_id:11, action: 'run'},
    {id: 3, tech_id:22, action: 'climb'},
    {id: 4, tech_id:22, action: 'swim'},
    {id: 5, tech_id:11, action: 'jump'},
]
  

Как мне сделать так, чтобы это выглядело так:

 [
    {tech_id: 11, data: [{id: 1, action:'swim'}, {id: 2, action:'run'}, {id: 5, action:'jump'}] }
    {tech_id: 22, data: [{id: 3, action:'climb'}, {id:4, action:'swim'}]}

]
  

Ответ №1:

Для этого вы могли бы использовать reduce with Object.keys .

 var arr = [
    {id: 1, tech_id:11, action: 'swim'},
    {id: 2, tech_id:11, action: 'run'},
    {id: 3, tech_id:22, action: 'climb'},
    {id: 4, tech_id:22, action: 'swim'},
    {id: 5, tech_id:11, action: 'jump'},
]

let mergeObj = arr.reduce((p, c) => {
    const {tech_id, ...otherData} = c;

    if (!(tech_id in p)) {
        p[tech_id] = {
            data: []
        }
    }
    
    p[tech_id].data.push(otherData)
    return p
}, {})

mergeObj = Object.keys(mergeObj).map(key => {
    return {
        tech_id: key,
        data: mergeObj[key].data
    }
})

console.log(mergeObj);  

Ответ №2:

Для этого можно использовать функцию уменьшения массива и значения объекта.

 var arr = [
{id: 1, tech_id:11, action: 'swim'},
{id: 2, tech_id:11, action: 'run'},
{id: 3, tech_id:22, action: 'climb'},
{id: 4, tech_id:22, action: 'swim'},
{id: 5, tech_id:11, action: 'jump'},
]
const result = Object.values(arr.reduce((item, next) => {
if (!item[next.tech_id]) {
    item[next.tech_id] = {
        tech_id: next.tech_id,
        data: []
    };
}

item[next.tech_id].data.push(next);
return item;
}, {}));

console.log(result);  

Ответ №3:

Одно из предложений состоит в том, чтобы использовать a Map , где каждый ключ на карте равен a tech_id , а каждое значение представляет собой массив объектов (за исключением tech_id ), которые имеют это tech_id . Затем вы можете преобразовать карту в массив с помощью Array .из с дополнительной функцией сопоставления для преобразования каждой [key, value] записи пары на карте в объект ([tech_id, data]) => ({tech_id, data}) :

 const arr = [ {id: 1, tech_id:11, action: 'swim'}, {id: 2, tech_id:11, action: 'run'}, {id: 3, tech_id:22, action: 'climb'}, {id: 4, tech_id:22, action: 'swim'}, {id: 5, tech_id:11, action: 'jump'}, ];
const res = Array.from(arr.reduce((map, {tech_id,  ...r}) => 
  map.set(tech_id, [...(map.get(tech_id) || []), r])
, new Map), ([tech_id, data]) => ({tech_id, data}));

console.log(res);  
 .as-console-wrapper { max-height: 100% !important;} /* ignore */