lodash通过多个键对数组进行分组

时间:2015-02-06 07:29:25

标签: javascript lodash

[更新]:我之前删除了大部分布局和lodash(失败的代码),因为JSON数据格式已经改变。

我正在尝试对数据集进行分组以准备汇总总计。这是传入的JSON布局。我需要按国家分组,然后按品牌分组:

  [
    {
      $id: "1",
      countryCode: "HT",
      brand: "CO",
      roomNights: 12,
      hotelSpend: 2000
     },
    {
     $id: "2",
     countryCode: "PK",
     brand: "HH",
     roomNights: 201,
     hotelSpend: 10000
    },
   {
     $id: "3",
     countryCode: "RO",
     brand: "CO",
     roomNights: 34,
     hotelSpend: 5000
    },
   { 
     $id: "4",
     countryCode: "US",
     brand: "ES",
     roomNights: 120,
     hotelSpend: 56000
   },
   {
     $id: "5",
     countryCode: "PK",
     brand: "HH",
     roomNights: 145,
     hotelSpend: 33000
   }
  ]

需要将数据转换为以下格式:

        ['Brand','HT'     , 'PK'        , 'US'     , 'RO', 'Avg Rm', 'Avg Spend']
        ['HH'   ,'0/0'    ,'201/10000', '0/0'       , '0/0'     , 201,   10000],
        ['CO'   ,'12/2000','0/0',     , '0/0'       , '34/5000', 23 ,    3500],
        ['ES'   , '0/0'    ,'0/0'    , '120/50000'  , '0/0'    , 120, 50000]

房间夜晚和hotelSpend将根据品牌和&国家和每个国家的平均值需要在最后计算字段。

谢谢!

1 个答案:

答案 0 :(得分:2)

我们首先定义一个mean函数并将其添加到_

_.mixin({
  mean: function(ds) {
    return _(ds).foldr(function(a, b) { return a + b; }, 0) / ds.length;
  }
}); 

让我们定义用于选择行和列的函数:

var row = function(d) { return d.brand; };
var col = function(d) { return d.countryCode; };

aggr函数获取我们数据的子列表,并将其值聚合为一个值(这里是有理数的字符串表示):

var aggr = function(ds) {
  var val = _(ds).foldr(function(a, b) {
    return {
      roomNights: a.roomNights + b.roomNights,
      hotelSpend: a.hotelSpend + b.hotelSpend
    };
  }, {roomNights: 0, hotelSpend: 0});

  return val.roomNights + "/" + val.hotelSpend;
};

我们的行和列标签:

rows = _.chain(data).map(row).unique().value();
columns = _.chain(data).map(col).unique().value();

枢轴:

[["Brand/Country"].concat(columns).concat(["Avg Rm", "Avg Spend"])] // header row
.concat(_(rows).map(function(r){

  // data in this row
  rdata = _(data).filter(function(d) { return row(d) == r; });

  return [r].concat(_(columns).map(function(c){
    return aggr(_(rdata).filter(function(d) {return col(d) == c; }));
  }))
  // the last two columns in each row
  .concat([
    _.chain(rdata).map(function(d) { return d.roomNights; }).mean().value(),
    _.chain(rdata).map(function(d) { return d.hotelSpend; }).mean().value()
  ]);
}));

您可以通过修改countryCodebrand数组来控制订单或按特定rowscolumns过滤结果,类似于电子表格。