0.1.1 • Published 7 years ago

bucketing v0.1.1

Weekly downloads
212
License
MIT
Repository
github
Last release
7 years ago

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 to group

  • labels: Label[]: a unique array of labels generated from the array of items. The key generated by the on 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.