Сопоставить ключи объекта с ключом - PullRequest
0 голосов
/ 22 октября 2019

У меня есть следующий объект:

[{animal: 1, hasLegs: true},{animal: 1, hasTail: false},
 {animal: 2, hasLegs: true},{animal: 2, hasTail: true},{animal: 3}]

Я хотел бы реструктурировать его следующим образом:

[
  { animal:1, info: { hasLegs: true, hasTail: false },
  { animal:2, info: { hasLegs: true, hasTail: true },
  { animal:3, into: {},
]

, чтобы все объекты в массиве с этим animal:1объединяется под этим ключом и добавляет остальные ключи со значениями под ключом info.

Пытался использовать функцию map(), но не может понять ее, и не знаю, *Один 1012 * может решить эту проблему.

Ответы [ 3 ]

2 голосов
/ 22 октября 2019

Это аналогичный ответ, но он должен быть несколько более производительным, поскольку он использует хеширование карты вместо поиска для каждой записи.

const data = [{animal: 1, hasLegs: true},{animal: 1, hasTail: false},
  {animal: 2, hasLegs: true},{animal: 2, hasTail: true},{animal: 3}]

const infoMap = data.reduce((rollup, { animal, ...info }) => {
  const entry = rollup[animal] = rollup[animal] || {}
  Object.assign(entry, info)
  return rollup
}, {})

const result = Object.keys(infoMap)
  .map((animal) => ({
    animal,
    info: infoMap[animal]
  }))

console.log(result)
2 голосов
/ 22 октября 2019

Я бы предложил создать объект поиска из исходного массива. Таким образом, вам не нужно просматривать весь массив на каждом элементе (что делает его O(n²)).

Итак, заранее учитывая наш список:

const animals = [
  { animal: 1, hasLegs: true },
  { animal: 1, hasTail: false },
  { animal: 2, hasLegs: true },
  { animal: 2, hasTail: true },
  { animal: 3 }
]

Мы создаемтаблица поиска с reduce, объединяющая каждый объект, который мы находим в исходном массиве, в объект значения животного:

const lookup = animals.reduce((acc, val) => {
  // use object destructuring and object spread to pick out
  // the "animal" field and the rest into separate variables
  const { animal, ...info } = val
  // get existing info object, or create new empty if not found
  const existingInfo = acc[animal] || {}
  // merge existing info and new info from this object
  acc[animal] = { ...existingInfo, ...info }
  return acc
}, {})

На этом этапе структура выглядит следующим образом:

{
  '1': { hasLegs: true, hasTail: false },
  '2': { hasLegs: true, hasTail: true },
  '3': {}
}

Теперь нам просто нужно пройти через этот объект, превратить его в массив и выбрать ключ в поле «животное»:

const after = Object.entries(lookup).map(([key, value]) => {
  return { animal: key, info: value }
})

Это дает желаемый результат:

[
  { animal: '1', info: { hasLegs: true, hasTail: false } },
  { animal: '2', info: { hasLegs: true, hasTail: true } },
  { animal: '3', info: {} }
]

Обратите внимание, что Object.entries может не поддерживаться в старых браузерах. Если вы ориентируетесь на старые браузеры, проверьте, как Робб Трэйстер делает это в своем ответе с Object.keys

1 голос
/ 22 октября 2019
const array = [{ animal: 1, hasLegs: true }, { animal: 1, hasTail: false },
{ animal: 2, hasLegs: true }, { animal: 2, hasTail: true }, { animal: 3 }];
const result = [];
array.forEach(obj => {
    let newEntry = null;
    if (result.findIndex(entry => entry.animal === obj.animal) === -1) {
        newEntry = { animal: obj.animal, info: {} }
        result.push(newEntry);
    }
    const entry = newEntry || result.find(entry => entry.animal === obj.animal);
    Object.keys(obj).forEach(key => {
        if (key === 'animal') return;
        entry.info[key] = obj[key];
    });

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