Lodash group by multiple properties if property value is true

独自空忆成欢 提交于 2019-11-27 06:00:48

问题


I have an array of vehicles that need to be grouped by make and model, only if the 'selected' property is true. The resulting object should contain properties for make model and count. Using lodash, how can I organize the vehicle objects into the desired result objects. I'm able to get the vehicle objects grouped by makeCode but I'm not sure how to group by more than one property.

group by make code works

      var vehicles = _.groupBy(response.vehicleTypes, function(item)
      {
        return item.makeCode; // how to group by model code as well
      });

initial vehicles

{
    id: 1, 
    selected: true, 
    makeCode: "Make-A", 
    modelCode: "Model-a", 
    trimCode: "trim-a", 
    yearCode: "2012"
},
{
    id: 2, 
    selected: false, 
    makeCode: "Make-A", 
    modelCode: "Model-a", 
    trimCode: "trim-a", 
    yearCode: "2013"
},
{
    id: 3, 
    selected: true, 
    makeCode: "Make-B", 
    modelCode: "Model-c", 
    trimCode: "trim-a", 
    yearCode: "2014"
},
{
    id: 25, 
    selected: true, 
    makeCode: "Make-C", 
    modelCode: "Model-b", 
    trimCode: "trim-b", 
    yearCode: "2012"
},
{
    id: 26, 
    selected: true, 
    makeCode: "Make-C", 
    modelCode: "Model-b", 
    trimCode: "trim-a", 
    yearCode: "2013"
}

result object

{
    Make-A: {
        Model-a: {
            count: 1
        }
    }
},

{
    Make-B: {
        Model-c: {
            count: 1
        }
    }
},
{
    Make-C: {
        Model-b: {
            count: 2
        }
    }
}

回答1:


Since you're already using lodash, you can take advantage of the _.filter function. This will return only the items where selected is true.

var selectedVehicles = _.filter(response.vehicleTypes, 'selected');

Now that you have the selectedVehicles array, you can use your original code for grouping by the makeCode.

selectedVehicles = _.groupBy(selectedVehicles, function(item) {
  return item.makeCode;
});

This returns an object, so we will need to iterate through those keys, and perform our second groupBy

_.forEach(selectedVehicles, function(value, key) {
  selectedVehicles[key] = _.groupBy(selectedVehicles[key], function(item) {
    return item.modelCode;
  });
});

From this you will have an object of the form. I'll leave it to you to get the count from each array.

{ 'Make-A': { 'Model-a': [ ... ] },
  'Make-B': { 'Model-c': [ ... ] },
  'Make-C': { 'Model-b': [ ..., ... ] } }



回答2:


I am not sure if this will solve Your problem, but in group_by You can add custom logic which allow You to create composite key.

_.chain(data).filter((item) => item.selected).groupBy((item)=>`${item.model}--${item.type}`)



回答3:


You can use Array.prototype.reduce(), and do it in one loop O(n):

var arr = [{"id":1,"selected":true,"makeCode":"Make-A","modelCode":"Model-a","trimCode":"trim-a","yearCode":"2012"},{"id":2,"selected":false,"makeCode":"Make-A","modelCode":"Model-a","trimCode":"trim-a","yearCode":"2013"},{"id":3,"selected":true,"makeCode":"Make-B","modelCode":"Model-c","trimCode":"trim-a","yearCode":"2014"},{"id":25,"selected":true,"makeCode":"Make-C","modelCode":"Model-b","trimCode":"trim-b","yearCode":"2012"},{"id":26,"selected":true,"makeCode":"Make-C","modelCode":"Model-b","trimCode":"trim-a","yearCode":"2013"},{"id":29,"selected":false,"makeCode":"Make-A","modelCode":"Model-g","trimCode":"trim-a","yearCode":"2013"},{"id":2,"selected":true,"makeCode":"Make-A","modelCode":"Model-h","trimCode":"trim-a","yearCode":"2013"}];

var result = arr.reduce(function(map, obj) {
  if(!obj.selected) {
    return map;
  }
  
  var makeCode = map[obj.makeCode] = map[obj.makeCode] || {};
  
  var modelCode = makeCode[obj.modelCode] = makeCode[obj.modelCode] || { count: 0 };
  
  modelCode.count++;
  
  return map;
}, Object.create(null));

console.log(result);



回答4:


const result = _.chain(vehicles)
.filter('selected')
.groupBy('makeCode')
.mapValues(values => _.chain(values)
    .groupBy('modelCode')
    .mapValues(_.size)
    .value()
)
.value()



回答5:


const multiGroupBy = (array, group, ...restGroups) => {
  if(!group) {
    return array;
  }
  const currGrouping = _.groupBy(array, group);
  if(!restGroups.length) {
    return currGrouping;
  }
  return _.transform(currGrouping, (result, value, key) => {
    result[key] = multiGroupBy(value, ...restGroups);
  }, {});
};

console.log(multiGroupBy([{x:1,y:1,z:1},{x:1,y:2,z:1},{x:2,y:1,z:1},{x:2,y:2,z:1},{x:1,y:1,z:2},{x:1,y:2,z:2},{x:2,y:1,z:2},{x:2,y:2,z:2}],'x','y'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

or if you prefer old syntax

function multiGroupBy(array, group) {
  if(!group) {
    return array;
  }
  var currGrouping = _.groupBy(array, group);
  var restGroups = Array.prototype.slice.call(arguments);
  restGroups.splice(0,2);
  if(!restGroups.length) {
    return currGrouping;
  }
  return _.transform(currGrouping, function(result, value, key) {
    result[key] = multiGroupBy.apply(null, [value].concat(restGroups));
  }, {});
}

console.log(multiGroupBy([{x:1,y:1,z:1},{x:1,y:2,z:1},{x:2,y:1,z:1},{x:2,y:2,z:1},{x:1,y:1,z:2},{x:1,y:2,z:2},{x:2,y:1,z:2},{x:2,y:2,z:2}],'x','y'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>



回答6:


Grouping and filtering an object or array without LODASH on pure JS:

// Группировка и фильтрация объекта или массива без LODASH на чистом JS:
let k = "HUID", // group by; 
input = [
{HUID:11,test:1},
{HUID:11,test:111},
{HUID:'eeeeeeeeeeee',test:11111},
{HUID:22,test:2},
{HUID:33,test:3}
],
result = input.reduce((map, obj) => { 
//if(!obj.selected) { return map; } 
let makeCode = (map[obj[k]] = map[obj[k]] || {}); // var modelCode = makeCode[obj.HUID] = makeCode[obj.HUID] || { count: 0 }; 
let l = map[obj[k]],
    m = Object.keys(l).length; 
l[m] = { ...obj }; 
return map; 
}, {} );
console.log(result);

Copied from VK



来源:https://stackoverflow.com/questions/40139667/lodash-group-by-multiple-properties-if-property-value-is-true

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!