【问题标题】:lodash chaining groupBylodash 链接 groupBy
【发布时间】:2016-08-05 22:24:34
【问题描述】:

我试图弄清楚如何将仅按装饰/年份唯一的车辆对象数组转换为数组嵌套对象属性。最初,我循环遍历所有属性以将车辆组织成数组的层次结构,即 make[model[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
         } 
       }
     }
   }
}

感谢您的帮助。

【问题讨论】:

    标签: object grouping lodash


    【解决方案1】:

    下面的解决方案使用_.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>');
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.js"&gt;&lt;/script&gt;

    【讨论】:

    • 哇,感谢您的回复。仍然试图解决这个问题。我尝试运行代码,但得到“_.setWith 不是函数”。我正在使用 lodash 版本 14.4.1,有什么想法吗?
    • 您确定您使用的 _ 变量是 lodash 而不是 undescore 吗?版本是4.14.1?请重新检查。
    • 是的,我没有使用下划线并验证了我的 lodash 版本 - "lodash": "4.14.1。如果我将其更改为 _.set 它似乎可以工作?
    • 它应该不起作用,尝试在问题中使用_.set() 添加您提到的代码,我会尝试检查它为什么会这样。
    • 暂时远离这个,但事实证明我正在使用的另一个库 pdfMake 包含它自己的 lodash 版本 3.10.1 的自定义构建。似乎可以通过更改它们的导入顺序来修复。再次感谢,伙计!
    猜你喜欢
    • 1970-01-01
    • 2018-03-18
    • 1970-01-01
    • 2021-10-15
    • 1970-01-01
    • 1970-01-01
    • 2020-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多