使用lodash进行分组和层次映射

时间:2019-03-05 08:26:49

标签: javascript lodash

我正在尝试使用Lodash groupBy并映射一些数据。这是示例数据:

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 :(得分:2)

您需要映射新对象并​​获取选择的值。

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>

答案 1 :(得分:0)

您无需为此使用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);

答案 2 :(得分:0)

您可以使用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);

答案 3 :(得分:0)

您的代码实际上不错,除了一个小错误。您以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>