bucketing
In two tiers, group an array of items into buckets. At its core this is not
entirely dissimilar to lodash.groupBy
,
but with a few differences:
-
Two-tiered:
lodash.groupBy
expects one function that takes an item and generates a key.bucketing
expects two functions: one that takes an item and generates a label, and one that takes a label and generates a key. This allows you to group objects by a complex object rather than strings, working around the fact that JavaScript objects can only have string or number keys. -
Auxiliary structures:
lodash.groupBy
returns just the resulting grouping.bucketing
returns the original items, a unique array of labels, the same usual buckets, as well as a map from key to label.
This module works with JavaScript as well as TypeScript out of the box.
Example
Given the following book data:
const mg = id: 'mg' name: 'Max Gladstone';const nm = id: 'nm' name: 'Neve Maslakovic';const ww = id: 'ww' name: 'Will Wight';const gf = id: 'gf' name: 'Gillian Flynn'; const books = title: 'Four Roads Cross' author: mg title: 'Gone Girl' author: gf title: 'Soulsmith' author: ww title: 'Regarding Ducks and Universes' author: nm title: 'Two Serpents Rise' author: mg title: 'Sharp Objects' author: gf;
We can group them by author on author ID:
; const groupings = ;
This gives us:
// The original:groupingsitems; // === books // The labels:groupingslabels; // equal to [mg, gf, ww, nm] // The buckets:groupingskeyToItems;/*equal to: { 'mg': [ {title: 'Four Roads Cross', author: mg}, {title: 'Two Serpents Rise', author: mg} ], 'gf': [ {title: 'Gone Girl', author: gf}, {title: 'Sharp Objects', author: gf} ], 'ww': [ {title: 'Soulsmith', author: ww}, ], 'nm': [ {title: 'Regarding Ducks and Universes', author: nm} ]}*/ // The map:groupingskeyToLabel;/*equal to: { 'mg': {id: 'mg', name: 'Max Gladstone'}, 'gf': {id: 'gf', name: 'Gillian Flynn'}, 'ww': {id: 'ww', name: 'Will Wight'}, 'nm': {id: 'nm', name: 'Neve Maslakovic'} }*/
API
group<T, L>(items: T[], by: T => L, on: L => string): Grouping
Takes items
, buckets them using the labels generated from the by
function,
and keys those labels using the keys generated from the on
function. Returns
a Grouping
. Please ensure that the on
function generates unique keys for a
given label. That is to say: no two labels should share the same key.
Grouping<Item, Label>
The Grouping<Item, Label>
type is the return type of group
. It contains
four things:
-
items: Item[]
: the original array of items passed togroup
-
labels: Label[]
: a unique array of labels generated from the array of items. The key generated by theon
function is used to determine label equality. -
keyToItems: ItemBuckets<Item>
: a map in which each key-value pair is a bucket. The key is the key of bucket's label, and the value is an array of items that all fall under said bucket. -
keyToLabel: LabelMap<Item>
: a map that maps from key to label.
ItemBuckets<Item>
A type defined as { [key: string]: Item[] }
. Conceptually an unordered list
of buckets. Each bucket has a label (whose key is the bucket's key) and
contains one or more items (in the bucket's value).
LabelMap<Label>
A type defined as { [key: string]: Label }
. Conceptually a map of keys to
labels.