web-dev-qa-db-fra.com

Lodash groupe par plusieurs propriétés si la valeur de la propriété est true

J'ai un tableau de véhicules qui doivent être regroupés par marque et par modèle, uniquement si la propriété 'selected' est vraie. L'objet résultant doit contenir des propriétés pour make model et count. Avec lodash, comment puis-je organiser les objets du véhicule en objets de résultat souhaités? Je peux obtenir les objets véhicule regroupés par makeCode mais je ne suis pas sûr de savoir comment grouper par plus d'une propriété.

groupe par make code works

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

véhicules initiaux

{
    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"
}

objet résultat

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

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

Puisque vous utilisez déjà lodash, vous pouvez utiliser la fonction _.filter . Cela renverra uniquement les éléments où selected est vrai.

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

Maintenant que vous avez le tableau selectedVehicles, vous pouvez utiliser votre code d'origine pour le regroupement par makeCode.

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

Cela retourne un objet, nous devrons donc parcourir ces clés et effectuer notre seconde groupBy

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

De cela, vous aurez un objet de la forme. Je vous laisse le soin de connaître le nombre de chaque tableau.

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

Je ne sais pas si cela résoudra votre problème, mais dans group_by, vous pouvez ajouter une logique personnalisée vous permettant de créer une clé composite. 

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

Vous pouvez utiliser Array.prototype.reduce() et le faire en une boucle 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
Ori Drori

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

0
Carlos Illobre

Grouper et filtrer un objet ou un tableau sans LODASH sur JS pur:

// Группировка и фильтрация объекта или массива без 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);

Copié de VK

0
kostia7alania

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>

ou si vous préférez l'ancienne syntaxe

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>

0
Amin