lodash 按多个键对数组进行分组

lodash grouping an array by multiple keys

[更新]:我删除了之前的大部分布局和 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]

roomNights 和 hotelSpend 将按品牌和国家汇总,最后需要计算每个字段的平均值。

谢谢!

我们先定义一个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()
  ]);
}));

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