Преобразование массива данных

Необходимо преобразовать массив вида:

[
    {
        name: 'John',
        data: { /* Данные */ }
    },
    {
        name: 'John',
        data: { /* Данные */ }
    },
    {
        name: 'John',
        data: { /* Данные */ }
    },
    {
        name: 'Tom',
        data: { /* Данные */ }
    },
    {
        name: 'Tom',
        data: { /* Данные */ }
    }
]

В такой:

[
    {
        name: 'John',
        data: [
            { /* Данные */ },
            { /* Данные */ },
            { /* Данные */ }
        ]
    },
    {
        name: 'Tom',
        data: [
            { /* Данные */ },
            { /* Данные */ }
        ]
    }
]

Сделать это нужно одним действием чем менее императивно тем лучше. У меня получился вот такой вариант, но я не уверен что это оптимальное решение.

const list = list.reduce((accum, curent)=> {
    const name = curent.name
    const isExist = accum.some(el=>el.name === name)

    if(accum.length === 0 || !isExist) {
        accum.push({
            name,
            data: []
        })
    }
    return accum.map((el) => {
        if(el.name === name) {
            el.data.push(curent.data)                   
        }
        return el
    })
}, [])

Ответы (1 шт):

Автор решения: Alexander Lonberg

const person = [
  { name: 'John', data: { 1: 'Данные' } },
  { name: 'John', data: { 2: 'Данные' } },
  { name: 'John', data: { 3: 'Данные' } },
  { name: 'Tom', data: { 1: 'Данные' } },
  { name: 'Tom', data: { 2: 'Данные' } }
]

function merge(arrData) {
  return Array.prototype.filter.call(arrData, function (v) {
    return this.has(v.name) ?
      (this.get(v.name).push(v.data), false) :
      (this.set(v.name, (v.data = [v.data])), true)
  }, new Map())
}
console.log(merge(person))

→ Ссылка