lodash chaining groupBy

时间:2016-08-05 22:24:35

标签: object grouping lodash

我试图弄清楚如何将一个车辆对象数组转换为数组嵌套对象属性,这些对象只有trim / year唯一。最初我循环遍历所有属性以将车辆组织成阵列的分层结构,即,[模型[trim [year []]]],但我认为通过对象属性查找车辆会更快,即,make.model.trim.year。我是一个lodash菜鸟,所以我不确定该怎么做。

返回的数据结构如下:

[
  {
    id:1
    makeCode:"Make1"
    modelCode:"Modela"
    selected:true
    trimCode:"D"
    yearCode:"2014"
  },
  {
    id:2
    makeCode:"Make1"
    modelCode:"Modela"
    selected:true
    trimCode:"D"
    yearCode:"2015"
  },
  {
    id:3
    makeCode:"Make1"
    modelCode:"Modela"
    selected:true
    trimCode:"D"
    yearCode:"2016"
  },
  {
    id:4
    makeCode:"Make1"
    modelCode:"Modela"
    selected:true
    trimCode:"LX"
    yearCode:"2014"
  },
  {
    id:5
    makeCode:"Make1"
    modelCode:"Modela"
    selected:true
    trimCode:"LX"
    yearCode:"2015"
  },
  {
    id:6
    makeCode:"Make1"
    modelCode:"Modela"
    selected:true
    trimCode:"LX"
    yearCode:"2016"
  },
  {
    id:7
    makeCode:"Make2"
    modelCode:"Modelb"
    selected:true
    trimCode:"D"
    yearCode:"2014"
  },
  {
    id:8
    makeCode:"Make2"
    modelCode:"Modelb"
    selected:true
    trimCode:"D"
    yearCode:"2015"
  },
  {
    id:9
    makeCode:"Make2"
    modelCode:"Modelb"
    selected:true
    trimCode:"D"
    yearCode:"2016"
  }
]

这样可以正确获取makeCode排序的对象:

vm.makeGroups = _.groupBy(vm.selectedVehcileTypes, function(v) { return v.makeCode});

但我想在每个级别都这样做,所以我有类似的东西:

vm.makeGroups = _.groupBy(vm.selectedVehcileTypes, function(v) { return v.makeCode});
vm.modelGroups = _.groupBy(vm.makeGroups, function(v) { return v.modelCode});
vm.trimGroups = _.groupBy(vm.modelGroups, function(v) { return v.trimCode});

基本上我想链接分组,以便最终结果如下:

{
  Make1: {
    modela: {
      D: {
           '2012': false,
           '2013': false 
           '2014': true // selected
         } 
       }
     }
   }
}

感谢任何帮助,谢谢。

1 个答案:

答案 0 :(得分:3)

以下解决方案使用_.reduce()_.setWith()的组合作为获取最终结果的主要功能。

// array: Collection of objects
// keysPath: The path of the of the 
//           property to set check _.setWith docs
// keyValue: The value of each property

function getResult(array, keysPath, keyValue) {
  // This is used to get the values from the keysPath
  var getValue = _.curry(_.get, 2);
  return _.reduce(array, function(result, item) {
    // get path
    var path = _.map(keysPath, getValue(item));
    // set property values, note that using `Object` as a customizer
    // makes sure that yearCode is not treated as an index of an array
    // but an index of an object
    return _.setWith(result, path, item[keyValue], Object);
  }, {});
}

var result = getResult(
  data,
  ['makeCode', 'modelCode', 'trimCode', 'yearCode'],
  'selected'
);



var data = [
  {
    id:1,
    makeCode:"Make1",
    modelCode:"Modela",
    selected:true,
    trimCode:"D",
    yearCode:"2014"
  },
  {
    id:2,
    makeCode:"Make1",
    modelCode:"Modela",
    selected:true,
    trimCode:"D",
    yearCode:"2015"
  },
  {
    id:3,
    makeCode:"Make1",
    modelCode:"Modela",
    selected:true,
    trimCode:"D",
    yearCode:"2016"
  },
  {
    id:4,
    makeCode:"Make1",
    modelCode:"Modela",
    selected:true,
    trimCode:"LX",
    yearCode:"2014"
  },
  {
    id:5,
    makeCode:"Make1",
    modelCode:"Modela",
    selected:true,
    trimCode:"LX",
    yearCode:"2015"
  },
  {
    id:6,
    makeCode:"Make1",
    modelCode:"Modela",
    selected:true,
    trimCode:"LX",
    yearCode:"2016"
  },
  {
    id:7,
    makeCode:"Make2",
    modelCode:"Modelb",
    selected:true,
    trimCode:"D",
    yearCode:"2014"
  },
  {
    id:8,
    makeCode:"Make2",
    modelCode:"Modelb",
    selected:true,
    trimCode:"D",
    yearCode:"2015"
  },
  {
    id:9,
    makeCode:"Make2",
    modelCode:"Modelb",
    selected:true,
    trimCode:"D",
    yearCode:"2016"
  }
];

function getResult(array, keysPath, keyValue) {
  var getValue = _.curry(_.get, 2);
  return _.reduce(array, function(result, item) {
    var path = _.map(keysPath, getValue(item));
    return _.setWith(result, path, item[keyValue], Object);
  }, {});
}

var result = getResult(
  data,
  ['makeCode', 'modelCode', 'trimCode', 'yearCode'],
  'selected'
);

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.js"></script>
&#13;
&#13;
&#13;