Простой способ превратить массив объектов в объект с сгруппированными ключами в виде массивов - PullRequest
0 голосов
/ 03 января 2019

Я ищу простой способ сделать следующее.Я пытался сделать это с lodash.reduce, и это неуклюже, есть ли более простой способ.

От:

[{a: 'meow'}, {a: 'woof'}]

Кому:

{a: ['meow', 'woof']}

Ответы [ 6 ]

0 голосов
/ 03 января 2019

Без использования каких-либо внешних библиотек или сокращений.

const input = [ {a: 'meow'}, {a: 'woof'}, {b: 'hi'}, {a: 'dog', c: 'bye'}, {} ];
let output = {};

input.forEach((inputObj) => {
  for(let key in inputObj){
    if(!output[ key ]){
      output[ key ] = [];
    }
    output[ key ].push(inputObj[key])
  }
});


console.log(output);
0 голосов
/ 03 января 2019

Вы можете использовать lodash # assignWith , чтобы назначить всем свойствам их соответствующие значения в одном объекте вместе с функцией настройщика, чтобы определить, как вы хотите структурировать объект.

const result = _.assignWith({}, ...data, (v = [], s) => v.concat(s));

Примечание. Чтобы убедиться, что мы не изменяем ни один из объектов в массиве data, я передал пустой объект в качестве первого параметра, который будет действовать как целевой объект.

const data = [
  { a: 'meow' },
  { a: 'woof', k: 'hey' },
  { k: 'yo', d: 'hehe' },
  { d: 'wazup', q: 'ohoho' }
];

const result = _.assignWith({}, ...data, (v = [], s) => v.concat(s));

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
0 голосов
/ 03 января 2019
    [{a: 'meow'}, {a: 'woof'}].reduce((m, n) => ({...m, [Object.keys(n)[0]]: (m[Object.keys(n)[0]] && m[Object.keys(n)[0]].concat(Object.values(n)[0])) || [].concat(Object.values(n)[0])}), {})
0 голосов
/ 03 января 2019

Один из вариантов - использовать два сокращения следующим образом:

const input = [{
  a: 'meow'
}, {
  a: 'woof'
}, {
  b: 'moo'
}];

const result = input
.reduce((itemResult, item) => Object.keys(item)
.reduce((keyResult, key) => ({
  ...keyResult,
  [key]: (keyResult[key] || []).concat(item[key])
}), itemResult), {});

console.log(result)

Не уверен, что это неуклюжий по сравнению с вашим текущим решением, но он довольно лаконичен и не требует внешней библиотеки.

0 голосов
/ 03 января 2019

Вы можете сделать это с чистым JS, без необходимости загрузки.

Вызовите метод reduce для массивов входного массива и уменьшите массив до объекта, циклически переключая ключи вашего внутреннего объекта:

const input = [{a: 'meow'}, {a: 'woof'}, {b: 'hi'}, {a: 'dog', c: 'bye'}, {}];

console.log(input.reduce((acc, val) => {
  Object.keys(val).forEach(key => {
    if(!acc[key]) {
      acc[key] = [];
    }
    acc[key].push(val[key]);
  });
  return acc;
}, {}));
0 голосов
/ 03 января 2019

У меня были некоторые проблемы с машинописью и lodash.reduce, это сработало.

export function getFuncsObject(funcs): Record<Funcs, Case[]> {
  let f = { ...funcs };
  f = lodash.mapValues(f, () => []);
  return f;
}

export function mockMerge(funcs, mocks: Record<Funcs, Case | null>[]): Record<Funcs, Case[]> {
  const f = getFuncsObject(funcs);
  lodash.each(mocks, (v, k) => {
    f[k].push(v);
  });
  return f;
}
...