jamesmcnamara / shades

A lodash-inspired lens-like library for Javascript
MIT License
413 stars 14 forks source link

Group by #33

Closed LukeDefeo closed 4 years ago

LukeDefeo commented 4 years ago

Hey im new to the library so apologies if this question is dumb or if this isn't the correct place.

Is it possible to do a group by like operation with shades. E.g in remeda you have

const users = [
  {name: 'john', age: 20, gender: 'm'},
  {name: 'marry', age: 22, gender: 'f'},
  {name: 'samara', age: 24, gender: 'f'},
  {name: 'paula', age: 24, gender: 'f'},
  {name: 'bill', age: 33, gender: 'm'},
]

R.pipe(
  users,
  R.filter(x => x.gender === 'f'),
  R.groupBy(x => x.age),
);
jamesmcnamara commented 4 years ago

Hey @LukeDefeo good question. Shades is broken into two pieces, the lens portion and the utilities for collections (map, filter, blah blah blah).

My design philosophy for the latter has been that shade's shouldn't replace your favorite collection processing library (Ramda, lodash/fp), but augment it. To this end, I only include a function if I think I can offer a variant that offers something new, which it typically does in two ways:

1. "Functor" Signatures

Most collections libraries that offer a map function offer it as a function that takes a List<A> and produces a List<B>. Shades however allows you to use the map function (or filter, find, etc.) to take in any collection type, and get that same collection type back. So if I map an object I get back and object, if I map a Map I get back a Map. Most importantly, it does this in a way that TypeScript can understand.

2. Shorthand Syntax

Most collections libraries (with the notable exception of Lodash) only work with functions, so you end up with noisy functions like:

R.groupBy(x => x.age)

shades' tries to accept a rich language for specifying an operation (strings, objects, functions), so that you can write things like:

const beatles = [{name: 'John', hits: 10}, {name: 'Paul', hits: 12}, {name: 'George', hits: 6}, {name: 'Ringo', hits: 1}]
R.pipe(
  beatles,
  filter({hits: greaterThan(9))
  map('name')
)
// ['John', 'Paul']

Again, it does this in a way that TypeScript can understand.

groupBy is pretty well covered by Ramda and lodash/fp. From an interface perspective, it only really makes sense for groupBy to take a collection and return an object, so there's no benefit to shades' polymorphic signatures. It might be nice to have the shorthand syntax for the function argument (i.e. to say:

groupBy('age')

), but shades exports into so you could always just do:

R.groupBy(into('age'))

TL;DR: Shades doesn't have anything to add to the groupBy function. Just pick your favorite from Ramda or lodash and use that!