Lodash group by multiple properties if property value is true

lodash group by multiple column
lodash groupby
lodash nested groupby
javascript array group by count
javascript split array into groups by property
lodash contains
lodash groupby return array
javascript array with multiple properties

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

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': [ ..., ... ] } }

Grouping by multiple properties using lodash, Creating composite objects from an array of “selected” objects is achieved with inital array of objects [ { id: 1, selected: true, makeCode: "Make-A", forEach(​selectedVehicles, function(value, key) { selectedVehicles[key] = _. Creating composite objects from an array of “selected” objects is achieved with filter and groupBy.

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}`)

Grouping elements in array by multiple properties, Also, if we first implement a general groupBy function, grouping by I find the functional aspect of JavaScript to be a big advantage. defineProperty('​groupByProperties', { value : function(properties){ // will However, I added groupByProperties as a non-enumerable property of Array.prototype so it  But I also need to call map function to calculate amount, so when I join orderBy on the end of chain like this: *.orderBy(function() {console.log(o)}) It will be print just number value which I calculated in map so I am not able order by some property of previous object. – stack001 stack001 Mar 19 '18 at 15:28

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);

template function, Creates an array of array values not included in the other given arrays using SameValueZero for equality comparisons. The `_.property` iteratee shorthand. _. findIndex except that it iterates over elements of collection from right to left. This method is like _.zip except that it accepts an array of grouped elements and​  The order of result values is determined by the order they occur in the array.The comparator is invoked with two arguments: (arrVal, othVal). When the comparator returns true, the items are considered duplicates and only the first occurrence will be included in the new array.

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

Objects, Creates an array excluding all values of the provided arrays using strict style callback will return true for elements that have the properties of the given object, else false . If a property name or object is provided it will be used to create a ".​pluck" or Creates an array of grouped elements, the first of which contains the first  Lodash group by multiple properties if property value is true. 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.

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>

multi level group by, lodash, collections · GitHub, Group collection's data by multiple iteratees @param {Array<String|​GroupByProp>} props Array of group by objects or This parameter also can contain both property names and group by objects together console.log('​deepEqual', true). _.differenceBy(array, [values], [iteratee=_.identity]) source npm package. This method is like _.difference except that it accepts iteratee which is invoked for each element of array and values to generate the criterion by which they're compared.

Lodash Group By - JSFiddle, http://stackoverflow.com/questions/24627026/lo-dash-array-grouping. 3 }).​value();. 15. document.body.innerHTML = '<pre>' + JSON.stringify(result, null, ' ') +  Lodash is released under the MIT license & supports modern environments. Review the build differences & pick one that’s right for you. // Load the full build. // Load the core build. // Load the FP build for immutable auto-curried iteratee-first data-last methods. // Load method categories. // Cherry-pick methods for smaller browserify/rollup

Underscore.js, Returns true if all of the values in the list pass the predicate truth test. string instead of a function, groups by the property named by iteratee on each of the values. Chunks an array into multiple arrays, each containing length or fewer items. Creates a lodash object which wraps value to enable implicit chaining. Methods that operate on and return arrays, collections, and functions can be chained together. Methods that retrieve a single value or may return a primitive value will automatically end the chain returning the unwrapped value.

Data Structures: Objects and Arrays :: Eloquent JavaScript, Objects allow us to group values—including other objects—to build more In the first case, we access the length property of the value in myString . When an object is written over multiple lines, indenting it like in the example helps Properties whose names aren't valid binding names or valid numbers have to be quoted. Lodash tutorial covers the Lodash JavaScript library. In this introductory Lodash tutorial, we cover Lodash functions in multiple examples. Lodash is a JavaScript library which provides utility functions for common programming tasks. It uses functional programming paradigm.

Comments
  • how about when there is a Make -T with Model-X and Model-Y
  • Thanks for stepping through this, makes perfect sense! I was over thinking it.
  • This method is more efficient as we only loop through the items once.
  • very good approach!
  • What does this statement do? var makeCode = map[obj.makeCode] = map[obj.makeCode] || {};
  • The main idea of my younger in this var makeCode = map[obj.makeCode] = map[obj.makeCode] || {}; is - assign map[obj.makeCode] or and empty object {} to map[obj.makeCode] (it's used as fallback in case map[obj.makeCode] doesn't exist yet), and assign map[obj.makeCode] to makeCode. I must admit, it's not the most readable code in the world. I'll tell that to my younger self when I meet him :)