简体   繁体   中英

How to combine Lodash _.forEach() with _.groupBy

I have an object with arrays of objects. I'm trying to loop through these arrays with _.forEach() and then group each array with _.groupBy(). But the function is just returning the original data.

 const testData = { "1": [ { name: "john", job: "programmer" }, { name: "jean", job: "dentist" }, { name: "jo", job: "programmer" }, { name: "jeff", job: "chef" }, { name: "jock", job: "dentist" } ], "2": [ { name: "julie", job: "doctor" }, { name: "billy", job: "clerk" }, { name: "carol", job: "doctor" }, { name: "claire", job: "clerk" }, { name: "cedric", job: "lawyer" } ] }; const groupedTest = data => { return _.forEach( data, arraygroup => { _.groupBy( arraygroup, obj => obj.job ); } ); }; const result = groupedTest(testData) console.log( result ); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script> 

I'm looking to return a new object with the arrays grouped by job, but this function is just returning the original data. I can't figure out where I've gone wrong with the logic :-( Thanks very much for any help you can give me..

_.forEach returns the original collection - use _.map and make sure you're returning everything.

 const testData = {"1":[{name:"john",job:"programmer"},{name:"jean",job:"dentist"},{name:"jo",job:"programmer"},{name:"jeff",job:"chef"},{name:"jock",job:"dentist"}],"2":[{name:"julie",job:"doctor"},{name:"billy",job:"clerk"},{name:"carol",job:"doctor"},{name:"claire",job:"clerk"},{name:"cedric",job:"lawyer"}]}; const groupedTest = data => _.map(data, arraygroup => _.groupBy(arraygroup, obj => obj.job)); const result = groupedTest(testData) console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: auto; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script> 

Another option would be to consider the use of built in functions Object.entries() and Array.reduce() to achieve what you require:

 const testData = { "1": [ { name: "john", job: "programmer" }, { name: "jean", job: "dentist" }, { name: "jo", job: "programmer" }, { name: "jeff", job: "chef" }, { name: "jock", job: "dentist" } ], "2": [ { name: "julie", job: "doctor" }, { name: "billy", job: "clerk" }, { name: "carol", job: "doctor" }, { name: "claire", job: "clerk" }, { name: "cedric", job: "lawyer" } ] }; /* Iterate key/value pairs of testData and reduce these to a new results object where values are nested grouping object */ const results = Object.entries(testData).reduce((output, [key,array]) => { /* Reduce array value to a group, where the grouping is based on the job key */ const group = array.reduce((result, item) => { if( Array.isArray( result[ item.job ] )) { /* If item.job key present in result (corresponding group) then add item to the key's group value */ result[ item.job ].push(item); } else { /* Otherwise, start a new group array for this yet unseen item.job key */ result[ item.job ] = [ item ]; } return result; }, {}); output[ key ] = group; return output; }, {}); console.log(results) 

The advantage of this approach is that it is independent of the loadash library

With lodash you could do _.values followed by _.map and then inside go with _.groupBy in order to get the grouping by job :

 const data = { "1": [ { name: "john", job: "programmer" }, { name: "jean", job: "dentist" }, { name: "jo", job: "programmer" }, { name: "jeff", job: "chef" }, { name: "jock", job: "dentist" } ], "2": [ { name: "julie", job: "doctor" }, { name: "billy", job: "clerk" }, { name: "carol", job: "doctor" }, { name: "claire", job: "clerk" }, { name: "cedric", job: "lawyer" } ] }; let result = _.map(_.values(data), arr => _.groupBy(arr, 'job')) console.log(result) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script> 

If you actually want to preserve the keys in the initial object then simply use _.mapValues with _.groupBy :

 const data = { "1": [ { name: "john", job: "programmer" }, { name: "jean", job: "dentist" }, { name: "jo", job: "programmer" }, { name: "jeff", job: "chef" }, { name: "jock", job: "dentist" } ], "2": [ { name: "julie", job: "doctor" }, { name: "billy", job: "clerk" }, { name: "carol", job: "doctor" }, { name: "claire", job: "clerk" }, { name: "cedric", job: "lawyer" } ] }; let result = _.mapValues(data, arr => _.groupBy(arr, 'job')) console.log(result) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script> 

Very similar and without the need of lodash you can do with ES6 :

 const data = { "1": [ { name: "john", job: "programmer" }, { name: "jean", job: "dentist" }, { name: "jo", job: "programmer" }, { name: "jeff", job: "chef" }, { name: "jock", job: "dentist" } ], "2": [ { name: "julie", job: "doctor" }, { name: "billy", job: "clerk" }, { name: "carol", job: "doctor" }, { name: "claire", job: "clerk" }, { name: "cedric", job: "lawyer" } ] }; let result = Object.values(data).map(x => x.reduce((r, {name, job}) => { r[job] = [...(r[job] || []), {name, job}] return r }, {})) console.log(result) 

Difference is that we achieve the group by via Array.reduce

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM