Группировка и иерархическое отображение с помощью lodash - PullRequest
0 голосов
/ 05 марта 2019

Я пытаюсь преобразовать некоторые данные, используя Lodash groupBy и map.Вот пример данных:

var data = [
{name: 'x', qty: 0, rate: 10},
{name: 'x', qty: 10, rate: 2},
{name: 'y', qty: 5, rate: 20},
{name: 'y', qty: 55, rate: 11}]

Мне нужны эти данные в формате:

var data = [
{name: 'x', pricing: [{qty: 0, rate: 10}, {qty: 10, rate: 2}]},
{name: 'y', pricing: [{qty: 5, rate: 20}, {qty: 55, rate: 11}]}]

Следующая моя попытка:

var m = _.chain(data)
.groupBy(data, 'name')
.map( function(i) {
  return {
    name: _.first(i).name,
    pricing: _.map(i, function(r) {
      return _.pick(r, ['qty', 'rate'])
    })
  }
})

Это производит

[{
    "name": "x",
    "pricing": [
      {"qty": 0, "rate": 10},
      {"qty": 10, "rate": 2},
      {"qty": 5,"rate": 20},
      {"qty": 55,"rate": 11}]
}]

Мне не удалось понять, что я делаю не так.Может быть, это даже не правильно, и есть лучший способ?

Ответы [ 4 ]

0 голосов
/ 05 марта 2019

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

Вам необходимо изменить .groupBy(data, 'name') на .groupBy('name').

Пример:

var data = [{ name: 'x', qty: 0, rate: 10 }, { name: 'x', qty: 10, rate: 2 }, { name: 'y', qty: 5, rate: 20 }, { name: 'y', qty: 55, rate: 11 }];

var m = _.chain(data)
  .groupBy('name') // group by name, and not by data, 'name'
  .map(function(i) {
    return {
      name: _.first(i).name,
      pricing: _.map(i, function(r) {
        return _.pick(r, ['qty', 'rate'])
      })
    }
  })

console.log(m);
.as-console-wrapper {
  max-height: 100% !important;
  top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
0 голосов
/ 05 марта 2019

Вы можете сделать это, используя reduce()

var data = [
{name: 'x', qty: 0, rate: 10},
{name: 'x', qty: 10, rate: 2},
{name: 'y', qty: 5, rate: 20},
{name: 'y', qty: 55, rate: 11}]

let res = data.reduce((ac,a) => {
  let i = ac.findIndex(x => x.name === a.name);
  if(i === -1) i = ac.push({name:a.name,pricing:[]}) - 1
  ac[i].pricing.push({qty:a.qty,rate:a.rate});
   return ac;
},[])
console.log(res);
0 голосов
/ 05 марта 2019

Вам необходимо отобразить новый объект и получить выбранные значения.

var data = [{ name: 'x', qty: 0, rate: 10 }, { name: 'x', qty: 10, rate: 2 }, { name: 'y', qty: 5, rate: 20 }, { name: 'y', qty: 55, rate: 11 }],
    result = _(data)
        .groupBy('name')
        .map((pricing, name) => ({
            name,
            pricing: _.map(pricing, _.partialRight(_.pick, ['qty', 'rate']))
        }))
        .value();

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
0 голосов
/ 05 марта 2019

Вам не нужно использовать lodash для этого - стандартные методы массива Javascript работают просто отлично.Уменьшите до объекта, индексированного на name, затем получите значения этого объекта:

var data = [
{name: 'x', qty: 0, rate: 10},
{name: 'x', qty: 10, rate: 2},
{name: 'y', qty: 5, rate: 20},
{name: 'y', qty: 55, rate: 11}]

const obj = data.reduce((a, { name, ...rest }) => {
  if (!a[name]) a[name] = { name, pricing: [] };
  a[name].pricing.push(rest);
  return a;
}, {});
const output = Object.values(obj);
console.log(output);
...