bucketing
v0.1.1
Published
group an array of items into buckets
Downloads
168
Maintainers
Readme
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:
import {group} from 'bucketing';
const groupings = group(
books,
book => book.author,
author => author.id
);
This gives us:
// The original:
groupings.items; // === books
// The labels:
groupings.labels; // equal to [mg, gf, ww, nm]
// The buckets:
groupings.keyToItems;
/*
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:
groupings.keyToLabel;
/*
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.