6 ms·
Using GroupBy on an array of objects in JavaScript
- mberning 5y agoI worked on a Ruby gem to add group_by and aggregate_by functions to collections/enumerables. I finished about 1/2 of the functionality and found the implementation to be hateful and thought it would be received poorly. Now seeing this I am second guessing myself.
- gfunk911 5y agoRuby already has group_by, unless I'm misunderstanding what you're saying
- caseyohara 5y agoEnumerable#group_by is in Ruby core https://ruby-doc.org/core-3.0.2/Enumerable.html#method-i-group_by https://ruby-doc.org/core-3.0.2/Enumerable.html#method-i-gro...
- deleted 5y ago[deleted]
- duxup 5y agoI was just doing something like this and thinking “I do this in SQL all the time but users like to change things up so much it should be a native array thing.”
- saranshk 5y agoall of lodash features would probably become a native thing soon enough
- yashap 5y agoPersonally I’d have this return a map instead of an object, so that the keys aren’t forced to be strings. Otherwise seems like a reasonable API, very similar to groupBy in any other moderately functional language, except with the “keys must be strings” restriction inherited from returning a plain object. Also, for those thinking JS objects can have non-string keys, they can’t, it just sometimes appears that way due to JS type coercion: https://www.becomebetterprogrammer.com/can-javasscript-object-keys-be-numbers-or-non-string-values/ https://www.becomebetterprogrammer.com/can-javasscript-objec... Edit: as pointed out by shawnz, this isn’t entirely accurate, JS object keys can also be symbols.
- shawnz 5y agoIt looks like they are also creating a "groupByToMap" for that reason. See: https://github.com/tc39/proposal-array-grouping https://github.com/tc39/proposal-array-grouping Property keys can also be symbol objects and it seems like that's supported by the groupBy function in addition to strings, see: https://tc39.es/proposal-array-grouping/ https://tc39.es/proposal-array-grouping/
- yashap 5y agoAh fair enough!
- saranshk 5y agoupdated the post with groupByToMap, Thanks for pointing that out.
- roebk 5y agoI wonder if groupBy should have had some sort of into argument. Otherwise, we may end up with four groupBy methods. groupBy, groupByToMap, groupByToWeakMap and groupByToRecord (should records land). Edit: this has already been discussed https://github.com/tc39/proposal-array-grouping/issues/3 https://github.com/tc39/proposal-array-grouping/issues/3
- beebeepka 5y agoKey strings can also contain emojis. Not that I would recommend it in most situations
- VWWHFSfQ 5y agoit's just utf8 bytes right
- masklinn 5y ago> Otherwise seems like a reasonable API, very similar to groupBy in any other moderately functional language Though lots of them implement the less useful but stream-able groupBy which only groups siblings matching the predicate (or key function).
- jbverschoor 5y agoOh lord… so you group by a Number, but the map-key becomes a String. Sounds like idiomatic JavaScript
- deleted 5y ago[deleted]
- throw_m239339 5y agoThis isn't a map, Javascript has a dedicated map type. In JavaScript, Objects keys can only be strings or symbols.
- saranshk 5y agogroupByToMap would be useful in that case as pointed out in another comment. Updated the post with that.
- ojr 5y agoJavascript has been so widely used for so long, there are two types of languages one that people hate and one that people don’t use
- ksbrooksjr 5y agoUnfortunately the typescript definitions for these two methods haven't been written yet [1]. [1] https://github.com/microsoft/TypeScript/issues/47171 https://github.com/microsoft/TypeScript/issues/47171
- mahesh_rm 5y agoWhere was this when I needed it? Happy discovery.
- saranshk 5y agoprobably would not have been written then, it is a stage 3 proposal but should be merged in hopefully soon.
- newlisp 5y agoI normally just write const groupBy = (fn, arr) => { return arr.reduce((o, e) => { const k = fn(e) if (o[k] !== undefined) o[k].push(e) else o[k] = [e] return o } Object.create(null)) }
- saranshk 5y agowhile there is nothing wrong with that, it's always good to have these things built-in as native functions instead.
- badjeans 5y agoHardly shorter than just writing the for loop, i.e. the example in python groupByAge = collections.defaultdict(list) for person in people: groupByAge[person["age"]].append(person)
- shhsshs 5y agoIn JS you would also need to check if the key exists first (so you can add it). I think the minimal example would be: const groupByAge = {} for (const person in people) { if (!groupByAge[person.age]) { groupByAge[person.age] = [] } groupByAge[person.age].push(person) } IMO it is a very nice change to now be able to write: const groupByAge = people.groupBy(p => p.age)
- SahAssar 5y agoA reduce version seems quite okay to me though, and keeps it pretty functional-styled. const groupByAge = people.reduce((previous, current) => { if (!previous[current.age]) previous[current.age] = [] previous[current.age].push(current) return previous }, {})
- zackmorris 5y agoFor what it's worth, the Laravel PHP framework (no affiliation) has the best introduction to higher-order methods for imperative programmers used to Javascript/C style of anything that I've come across: https://laravel.com/docs/master/collections https://laravel.com/docs/master/collections Most of these methods are also available as part of the Eloquent ORM, for filtering/reshaping queries before they're executed: https://laravel.com/docs/master/eloquent https://laravel.com/docs/master/eloquent Since being exposed to this way of working, I rarely use foreach() anymore, much less for(). The main downside being that I find most other languages tedious to work in now. LINQ in .NET/C# is nice, there might be others.
- chris-orgmenta 5y agoGreat - lodash needed a little less now. Though I do often see people using a combination of maps, filters, reduces, lodash functions etc. one by one, rather than doing everything in a single for in loop. In most cases it feels that For In is still the most performant option, as you want to manipulate the data in more ways than just grouping