Skip to content

kourge/bucketing

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

About

group an array of items into buckets

Resources

License

Stars

Watchers

Forks

Packages

No packages published