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

Я ищу компактное решение lodash, чтобы взять массив объектов, а затем создать новый объект с ключами объектов в массиве и уникальными значениями для каждого ключа.

[
    {
        color: "black",
        type: "bag",
    },
    {
        color: "red",
        type: "pants",
    },
    {
        color: "black",
        type: "jacket",
    },
]

Желаемый вывод:

{
    color: ["black", "red"],
    type: ["bag", "pants", "jacket"],
}

Спасибо!

Ответы [ 3 ]

0 голосов
/ 24 июня 2018

Вы можете решить эту проблему, используя lodash#flatMap с итерацией lodash#toPairs, чтобы создать плоскую версию пары ключей и значений в массиве.Используйте lodash#groupBy с функцией iteratee, которая удаляет ключ пар массивов, Array#shift, и используйте такое значение в качестве ключа группировки для коллекции.Наконец, используйте lodash#mapValues с итератором, состоящим из lodash#flatten и lodash#uniq, чтобы сгладить массив и получить только уникальные значения длякаждый сгруппированный массив.Обратите внимание, что при компоновке функции lodash#flow используется для составления последовательных аргументов функции для формирования одного функционального результата.

var result = _(array)
  .flatMap(_.toPairs)
  .groupBy(v => v.shift())
  .mapValues(_.flow(_.flatten, _.uniq))
  .value();

var array = [
    {
        color: "black",
        type: "bag",
    },
    {
        color: "red",
        type: "pants",
    },
    {
        color: "black",
        type: "jacket",
    }
];

var result = _(array)
  .flatMap(_.toPairs)
  .groupBy(v => v.shift())
  .mapValues(_.flow(_.flatten, _.uniq))
  .value();
  
console.log(result);
.as-console-wrapper{min-height:100%;top:0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
0 голосов
/ 24 июня 2018

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

const arr = [{color: "black",type: "bag",},{color: "red",type: "pants",},{color: "black",type:"jacket",}],
obj = arr.reduce((h, y) => {
  Object.keys(y).forEach(k => {
    if (!h[k]) {
      h[k] = []
      h[k].push(y[k])
    } else if (!h[k].includes(y[k])) h[k].push(y[k])
  })
  return h
}, {})
console.log(obj)
0 голосов
/ 23 июня 2018

Я не вижу функции, которая сделает это за вас, поэтому вот решение, которое решает проблему за несколько простых шагов, используя только функции lodash.

const listOfPairs = _.flatten(_.map(input, _.toPairs))

преобразует списокобъекты в список пар [ключ, значение]

listOfPairs = [
  [ 'color', 'black' ],
  [ 'type', 'bag' ],
  [ 'color', 'red' ],
  [ 'type', 'pants' ] ]

Теперь мы можем сгруппировать их по значениям в первой позиции в каждой паре.

const indexByKeyToValues = _.toPairs(_.groupBy(listOfPairs, _.head))

, что даетus

indexByKeyToValues = [
  [ 'color', [ ['color', 'black'], ['color', 'red'] ] ],
  [ 'type', [ ['type', 'bag'], ['type', 'pants'] ] ] ]

затем сопоставьте массивы значений, чтобы выбрать последний элемент (исходные значения на входных картах)

const pairsOfKeyAndValue = _.map(indexByKeyToValues, ([k, vs]) => [k, _.map(vs, _.last)])

, который почти существует

pairsOfKeyAndValue = [
  [ 'color', [ 'black', 'red' ] ],
  [ 'type', [ 'bag', 'pants' ] ] ]

нам просто нужно перестроить объект, используя эти пары

const result = _.fromPairs(pairsOfKeyAndValue)

Весь трюк "преобразования карты в последовательности пар и из пар" действительно распространен в функциональном программировании для выполнения такой обработки.Как только вы это сделаете, выяснить остальные шаги не так сложно.

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

...