Как денормализовать массив в JS - PullRequest
0 голосов
/ 12 июня 2019

У меня есть набор данных следующей формы

let data = [
  {
    "id": {
      "primary": "A1"
    },
    "msg": 1
  }, {
    "id": {
      "primary": "A1"
    },
    "msg": 2
  }, {
    "id": {
      "primary": "B2"
    },
    "msg": 3
  }
]

Я хотел бы преобразовать его в

newData = [
  {
    "id": {
      "primary": "A1"
    },
    "items": [
      { "msg": 1 },
      { "msg": 2 }
    ]
  },
  {
    "id": {
      "primary": "B2"
    },
    "items": [
      { "msg": 3 }
    ]
  }
]

Я думаю, что метод похож на следующий, но это не такв этом случае убедитесь, как проверить значения undefined.

let newData = [];
for (let i = 0; i < data.length; i++) {
  if (newData[i]['id']['primary'] === data[i]['id']) newData.push(data[i]['id'])
  else newData[i]['items'].push(data[i]['msg'])
}

Как преобразовать исходный набор данных, чтобы объединить записи с совпадающими primary id?

Ответы [ 2 ]

3 голосов
/ 12 июня 2019

Одним из вариантов будет использование .reduce() для создания нового массива из существующего.

Я добавил комментарии, чтобы уточнить.

let data = [ { "id": { "primary": "A1" }, "msg": 1 }, { "id": { "primary": "A1" }, "msg": 2 }, { "id": { "primary": "B2" }, "msg": 3 } ];

let result = data.reduce((out,item) => {
  let {id, ...items} = item;                      //Separate the "id" and "everything else"
  let existing = out.find(({id}) => id.primary == item.id.primary); 

  existing                                        //have we seen this ID already?
    ? existing.items.push(items)                  //yes - add the items to it
    : out.push({ id: {...id}, items: [items]});   //no - create it
    
  return out;
  }, []);
  
console.log(result);

Пара замечаний:

  • Вы можете заметить, что я установил идентификатор, используя id: {...id}, несмотря на id уже будучи объектом.Это потому, что использование существующего объекта id создаст ссылку , тогда как {...id} создает поверхностную копию .

  • У меня естьНе указано нигде свойство msg.Вместо этого любые свойства, которые не являются id, будут добавлены в список items (пример ниже) .

        let data = [ { "id": { "primary": "A1" }, "msg": 1, "otherStuff": "Hello World!" }, { "id": { "primary": "A1" }, "msg": 2, "AnotherThing": true }, { "id": { "primary": "B2" }, "msg": 3, "someOtherProperty": false } ];
    
        let result = data.reduce((out,item) => {
          let {id, ...items} = item;
          let existing = out.find(({id}) => id.primary == item.id.primary); 
    
          existing
            ? existing.items.push(items)
            : out.push({ id: {...id}, items: [items]});
            
          return out;
          }, []);
          
        console.log(result);

    Тем не менее, если вы начнете вкладывать объекты (кроме ID), они, вероятно, будут включены в качестве ссылок;...items является только мелкой копией.

    Если такой случай, рассмотрите что-то вроде JSON.parse(JSON.stringify(...)) для глубокой копии.Не забудьте прочитать ссылку, хотя;Есть предостережения.

1 голос
/ 13 июня 2019

Вы также можете решить эту проблему кратко, используя Array.reduce и ES6 :

let data = [ { "id": { "primary": "A1" }, "msg": 1 }, { "id": { "primary": "A1" }, "msg": 2 }, { "id": { "primary": "B2" }, "msg": 3 } ]

let result = data.reduce((r, {id, msg}) => 
  ((r[id.primary] = r[id.primary] || { id, items: [] }).items.push({msg}), r), {})

console.log(Object.values(result))

В более читаемом формате это:

let data = [ { "id": { "primary": "A1" }, "msg": 1 }, { "id": { "primary": "A1" }, "msg": 2 }, { "id": { "primary": "B2" }, "msg": 3 } ]

let result = data.reduce((r, {id, msg}) => {
  r[id.primary] = (r[id.primary] || { id, items: [] })
  r[id.primary].items.push({msg})
  return r
}, {})

console.log(Object.values(result))

Идея состоит в том, чтобы сгруппировать по id.primary, а затем, после того как группирование выполнено, просто получить значения через Object.values

Обратите внимание, что эторешение за один проход, при котором вам не нужно на каждую итерацию делать Array.find против текущего аккумулятора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...