Сократить многомерный массив объектов в единый массив объектов - PullRequest
2 голосов
/ 12 марта 2019

У меня есть этот многомерный массив объектов -

const initialArray = [
  {
   name: 'aaa', 
   value:[{id:1, data:1}, {id:2, data:2}, {id:3, data:3}]
  },
  {
   name: 'bbb', 
   value:[{id:1, data:4}, {id:2, data:5}, {id:3, data:6}]
  },
  {
   name: 'ccc', 
   value:[{id:1, data:7}, {id:2, data:8}, {id:3, data:7}]
  },
  {
   name: 'ddd', 
   value:[{id:1, data:2}, {id:2, data:1}, {id:3, data:1}]
  }
]

Мне нужно преобразовать его в этот массив -

const finalArray = [
  {
    id: 1, aaa: 1, bbb: 4, ccc: 7, ddd: 2
  },
  {
    id: 2, aaa: 2, bbb: 5, ccc: 8, ddd: 1
  },
  {
    id: 3, aaa: 3, bbb: 6, ccc: 7, ddd: 1
  }
]

Решение, которое у меня есть сейчас, -

initialArray.reduce((accum, arrayData) => {
  arrayData.value.forEach(element => {
    if (accum.some(el => el.id === element.id)) {
      accum.find(el => el.id === element.id)[arrayData.name] = element.data;
    } else {
        accum.push({ id: element.id, [arrayData.name]: element.data });
    }
  });
  return accum;
}, []);

Есть ли лучший и более элегантный способ сделать это?Я пытаюсь сделать это, уменьшив количество итераций в каждом массиве, уменьшив код и читабельность.Как вы можете видеть, некоторые и находят во время каждой итерации увеличивает количество итераций.Есть ли способ уменьшить его?

Ответы [ 3 ]

5 голосов
/ 12 марта 2019

function tranform(array) {
  const obj = {}
  
  array.forEach(({name, value}) => (value || []).forEach(({id, data}) => obj[id] = { id, ...obj[id], [name]: data } ))
  
  return Object.values(obj)
}

const initialArray = [
  {
   name: 'aaa', 
   value:[{id:1, data:1}, {id:2, data:2}, {id:3, data:3}]
  },
  {
   name: 'bbb', 
   value:[{id:1, data:4}, {id:2, data:5}, {id:3, data:6}]
  },
  {
   name: 'ccc', 
   value:[{id:1, data:7}, {id:2, data:8}, {id:3, data:7}]
  },
  {
   name: 'ddd', 
   value:[{id:1, data:2}, {id:2, data:1}, {id:3, data:1}]
  }
]

console.log(tranform(initialArray))
1 голос
/ 12 марта 2019

Вы можете взять Map для сбора объектов с одинаковыми id.

var initialArray = [{ name: 'aaa', value: [{ id: 1, data: 1 }, { id: 2, data: 2 }, { id: 3, data: 3 }] }, { name: 'bbb', value: [{ id: 1, data: 4 }, { id: 2, data: 5 }, { id: 3, data: 6 }] }, { name: 'ccc', value: [{ id: 1, data: 7 }, { id: 2, data: 8 }, { id: 3, data: 7 }] }, { name: 'ddd', value: [{ id: 1, data: 2 }, { id: 2, data: 1 }, { id: 3, data: 1 }] }],
    result = Array.from(initialArray
        .reduce(
            (m, { name, value }) => value.reduce(
                (n, { id, data }) => n.set(id, Object.assign(
                    n.get(id) || { id },
                    { [name]: data }
                )),
                m
            ),
            new Map
        )
        .values()
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 13 марта 2019

Вот то, что мне кажется читабельным (обратите внимание, что я проголосовал за закрытие вашего вопроса, потому что «в основном основан на мнении»):

initial = [{ 
  name : "aaa",
  value : [
    { id : 1, data : 1 },
    { id : 2, data : 2 },
    { id : 3, data : 3 }
  ]
}, {
  name : "bbb",
  value : [
    { id : 1, data : 4 },
    { id : 2, data : 5 },
    { id : 3, data : 6 }
  ]
}, {
  name : "ccc",
  value : [
    { id : 1, data : 7 },
    { id : 2, data : 8 },
    { id : 3, data : 7 }
  ]
}, {
  name : "ddd",
  value : [
    { id : 1, data : 2 },
    { id : 2, data : 1 },
    { id : 3, data : 1 }
  ]
}];

map = {};
final = [];

for (i = 0; i < initial.length; i++) {
  x = initial[i];
  for (j = 0; j < x.value.length; j++) {
    y = x.value[j];
    if (!map[y.id]) map[y.id] = { id: y.id };
    map[y.id][x.name] = y.data;
  }
}

for (k in map) {
  final.push(map[k]);
}

for (i = 0; i < final.length; i++) {
  console.log(JSON.stringify(final[i]));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...