• Stars
    star
    149
  • Rank 248,619 (Top 5 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 7 years ago
  • Updated about 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Typical random-related functions for JavaScript and TypeScript.

Build Status

Pandemonium

Pandemonium is a dead simple JavaScript/TypeScript library providing typical random-related functions such as choice, sample etc.

The library also provides a way to create any of the available functions using a custom random source (seedrandom, for instance).

Installation

npm install --save pandemonium

Usage

Summary

Typical helpers

Sampling

n being the number of items in the sampled sequence and k being the number of items to be sampled.

Method Time Memory Note
dangerouslyMutatingSample O(k) O(k) Must be able to mutate given array to work.
fisherYatesSample O(n) O(n) Probably not a good idea.
geometricReservoirSample O(k*log(n/k)) O(k) Probably the best way of sampling from a random access data structure.
naiveSample Ω(k), O(∞) O(k) Only useful if k << n.
reservoirSample O(n) O(k) Useful if pulling a sample from a stream.
sampleWithReplacements O(k) O(k) Performant but allows replacements.
samplePairs Ω(k), O(∞) O(k) Variant of naiveSample for unordered pairs.
sampleOrderedPairs Ω(k), O(∞) O(k) Variant of naiveSample for ordered pairs.
weightedReservoirSample O(n) O(k) Variant of reservoirSample working with weighted items.

choice

Function returning a random item from the given array.

import choice from 'pandemonium/choice';
// Or
import {choice} from 'pandemonium';

choice(['apple', 'orange', 'pear']);
>>> 'orange'

// To create your own function using custom RNG
import {createChoice} from 'pandemonium/choice';

const customChoice = createChoice(rng);

random

Function returning a random integer between given a & b.

import random from 'pandemonium/random';
// Or
import {random} from 'pandemonium';

random(3, 7);
>>> 4

// To create your own function using custom RNG
import {createRandom} from 'pandemonium/random';

const customRandom = createRandom(rng);

randomBoolean

Function returning a random boolean.

import randomBoolean from 'pandemonium/random-boolean';
// Or
import {randomBoolean} from 'pandemonium';

randomBoolean();
>>> true

// To create your own function using custom RNG
import {createrandomBoolean} from 'pandemonium/random-boolean';

const customRandomBoolean = createRandomBoolean(rng);

randomFloat

Function returning a random float between given a & b.

import randomFloat from 'pandemonium/random-float';
// Or
import {randomFloat} from 'pandemonium';

randomFloat(-5, 55);
>>> 6.756482

// To create your own function using custom RNG
import {createRandomFloat} from 'pandemonium/random-float';

const customRandomFloat = createRandomFloat(rng);

randomIndex

Function returning a random index of the given array.

import randomIndex from 'pandemonium/random-index';
// Or
import {randomIndex} from 'pandemonium';

randomIndex(['apple', 'orange', 'pear']);
>>> 1

// Alternatively, you can give the array's length instead
randomIndex(3);
>>> 2

// To create your own function using custom RNG
import {createRandomIndex} from 'pandemonium/random-index';

const customRandomIndex = createRandomIndex(rng);

randomString

Function returning a random string.

import randomString from 'pandemonium/random-string';
// Or
import {randomString} from 'pandemonium';

// To generate a string of fixed length
randomString(5);
>>> 'gHepM'

// To generate a string of variable length
randomString(3, 7);
>>> 'hySf3'

// To create your own function using custom RNG
import {createRandomString} from 'pandemonium/random-string';

const customRandomString = createRandomString(rng);

// If you need a custom alphabet
const customRandomString = createRandomString(rng, 'ATGC');

randomUint32

Function returning a random unsigned 32bits number.

import {randomUint32} from 'pandemonium/random-typed-int';
// Or
import {randomUint32} from 'pandemonium';

randomUint32();
>>> 397536

// To create your own function using custom RNG
import {createRandomUint32} from 'pandemonium/random-typed-int';

const customRandomUint32 = createRandomUint32(rng);

randomPair

Function returning a random pair from the given array.

Note that this function will return unordered pairs (i.e. [0, 1] and [1, 0] are to be considered the same) and will not return pairs containing twice the same item (i.e. [0, 0]).

import randomPair from 'pandemonium/random-pair';
// Or
import {randomPair} from 'pandemonium';

randomPair(['apple', 'orange', 'pear', 'cherry']);
>>> ['orange', 'cherry']

// Alternatively, you can give the array's length instead and get a pair of indices
randomPair(4);
>>> [1, 3]

// To create your own function using custom RNG
import {createRandomPair} from 'pandemonium/random-pair';

const customRandomPair = createRandomPair(rng);

randomOrderedPair

Function returning a random ordered pair (i.e. [0, 1] won't be considered to be the same as [1, 0]) from the given array.

import randomOrderedPair from 'pandemonium/random-ordered-pair';
// Or
import {randomOrderedPair} from 'pandemonium';

randomOrderedPair(['apple', 'orange', 'pear', 'cherry']);
>>> ['cherry', 'apple']

// Alternatively, you can give the array's length instead and get a pair of indices
randomOrderedPair(4);
>>> [3, 0]

// To create your own function using custom RNG
import {createRandomOrderedPair} from 'pandemonium/random-ordered-pair';

const customRandomPair = createRandomOrderedPair(rng);

shuffle

Function returning a shuffled version of the given array using the Fisher-Yates algorithm.

If what you need is to shuffle the original array in place, check out shuffleInPlace.

import shuffle from 'pandemonium/shuffle';
// Or
import {shuffle} from 'pandemonium';

shuffle(['apple', 'orange', 'pear', 'pineapple']);
>>> ['pear', 'orange', 'apple', 'pineapple']

// To create your own function using custom RNG
import {createShuffle} from 'pandemonium/shuffle';

const customShuffle = createShuffle(rng);

shuffleInPlace

Function shuffling the given array in place using the Fisher-Yates algorithm.

import shuffleInPlace from 'pandemonium/shuffle-in-place';
// Or
import {shuffleInPlace} from 'pandemonium';

const array = ['apple', 'orange', 'pear', 'pineapple'];
shuffleInPlace(array);

// Array was mutated:
array >>> ['pear', 'orange', 'apple', 'pineapple'];

// To create your own function using custom RNG
import {createShuffleInPlace} from 'pandemonium/shuffle-in-place';

const customShuffleInPlace = createShuffleInPlace(rng);

weightedChoice

Function returning a random item from the given array of weights.

Note that weights don't need to be relative.

import weightedChoice from 'pandemonium/weighted-choice';
// Or
import {weightedChoice} from 'pandemonium';

const array = [.1, .1, .4, .3, .1];
weightedChoice(array);
>>> .4

// To create your own function using custom RNG
import {createWeightedChoice} from 'pandemonium/weighted-choice';

const customWeightedChoice = createWeightedChoice(rng);

// If you have an array of objects
const customWeightedChoice = createWeightedChoice({
  rng: rng,
  getWeight: (item, index) => {
    return item.weight;
  }
});

const array = [{fruit: 'pear', weight: 4}, {fruit: 'apple', weight: 30}];
customWeightedChoice(array);
>>> 'apple'


// If you intent to call the function multiple times on the same array,
// you should use the cached version instead:
import {createCachedWeightedChoice} from 'pandemonium/weighted-choice';

const array = [.1, .1, .4, .3, .1];
const customWeightedChoice = createCachedWeightedChoice(rng, array);

customWeightedChoice();
>>> .3

weightedRandomIndex

Function returning a random index from the given array of weights.

Note that weights don't need to be relative.

import weightedRandomIndex from 'pandemonium/weighted-random-index';
// Or
import {weightedRandomIndex} from 'pandemonium';

const array = [.1, .1, .4, .3, .1];
weightedRandomIndex(array);
>>> 2

// To create your own function using custom RNG
import {createWeightedRandomIndex} from 'pandemonium/weighted-random-index';

const customWeightedRandomIndex = createWeightedRandomIndex(rng);

// If you have an array of objects
const customWeightedRandomIndex = createWeightedRandomIndex({
  rng: rng,
  getWeight: (item, index) => {
    return item.weight;
  }
});

const array = [{fruit: 'pear', weight: 4}, {fruit: 'apple', weight: 30}];
customWeightedRandomIndex(array);
>>> 1


// If you intent to call the function multiple times on the same array,
// you should use the cached version instead:
import {createCachedWeightedRandomIndex} from 'pandemonium/weighted-random-index';

const array = [.1, .1, .4, .3, .1];
const customWeightedRandomIndex = createCachedWeightedRandomIndex(rng, array);

customWeightedRandomIndex();
>>> 3

dangerouslyMutatingSample

Function returning a random sample of size k from the given array.

This function runs in O(k) time & memory but is somewhat dangerous because it will mutate the given array while performing its Fisher-Yates shuffle before reverting the mutations at the end.

import dangerouslyMutatingSample from 'pandemonium/dangerously-mutating-sample';
// Or
import {dangerouslyMutatingSample} from 'pandemonium';

dangerouslyMutatingSample(2, ['apple', 'orange', 'pear', 'pineapple']);
>>> ['apple', 'pear']

// To create your own function using custom RNG
import {createDangerouslyMutatingSample} from 'pandemonium/dangerously-mutating-sample';

const customSample = createDangerouslyMutatingSample(rng);

fisherYatesSample

Function returning a random sample of size k from the given array.

This function uses a partial Fisher-Yates shuffle and therefore runs in O(k) time but must clone the given array to work, which adds O(n) time & memory.

import fisherYatesSample from 'pandemonium/fisher-yates-sample';
// Or
import {fisherYatesSample} from 'pandemonium';

fisherYatesSample(2, ['apple', 'orange', 'pear', 'pineapple']);
>>> ['apple', 'pear']

// To create your own function using custom RNG
import {createFisherYatesSample} from 'pandemonium/fisherYatesSample';

const customFisherYatesSample = createFisherYatesSample(rng);

geometricReservoirSample

Function returning a random sample of size k from the given array.

This function runs in O(k * (1 + log(n / k))) time & O(k) memory using "Algorithm L" taken from the following paper:

Li, Kim-Hung. "Reservoir-sampling algorithms of time complexity O(n (1+ log (N/n)))." ACM Transactions on Mathematical Software (TOMS) 20.4 (1994): 481-493.

Note that this function is able to sample indices without requiring you to represent the range of indices in memory.

import geometricReservoirSample from 'pandemonium/geometric-reservoir-sample';
// Or
import {geometricReservoirSample} from 'pandemonium';

geometricReservoirSample(2, ['apple', 'orange', 'pear', 'pineapple']);
>>> ['apple', 'pear']

// Alternatively, you can pass a length and get a sample of indices back
geometricReservoirSample(2, 4);
>>> [0, 2]

// To create your own function using custom RNG
import {createGeometricReservoirSample} from 'pandemonium/geometric-reservoir-sample';

const customSample = createGeometricReservoirSample(rng);

naiveSample

Function returning a random sample of size k from the given array.

This function works by keeping a Set of the already picked items and choosing a random item in the array until we have the desired k items.

While it is a good pick for cases when k is little compared to the size of your array, this function will see its performance drop really fast when k becomes proportionally bigger.

Note that this function is able to sample indices without requiring you to represent the range of indices in memory.

import naiveSample from 'pandemonium/naive-sample';
// Or
import {naiveSample} from 'pandemonium';

naiveSample(2, ['apple', 'orange', 'pear', 'pineapple']);
>>> ['apple', 'pear']

// Alternatively, you can pass a length and get a sample of indices back
naiveSample(2, 4);
>>> [0, 2]

// To create your own function using custom RNG
import {createNaiveSample} from 'pandemonium/naive-sample';

const customSample = createNaiveSample(rng);

reservoirSample

Function returning a random sample of size k from the given array.

This function runs in O(n) time and O(k) memory.

A helper class able to work on an arbitrary stream of data that does not need to fit into memory is also available if you need it.

import reservoirSample from 'pandemonium/reservoir-sample';
// Or
import {reservoirSample} from 'pandemonium';

reservoirSample(2, ['apple', 'orange', 'pear', 'pineapple']);
>>> ['apple', 'pear']

// To create your own function using custom RNG
import {createReservoirSample} from 'pandemonium/reservoir-sample';

const customReservoirSample = createReservoirSample(rng);

// To use the helper class
import {ReservoirSampler} from 'pandemonium/reservoir-sample';

// If RNG is not provided, will default to Math.random
const sampler = new ReservoirSampler(10, rng);

for (const value of lazyIterable) {
  sampler.process(value);
}

// To retrieve the sample once every value has been consumed
const sample = sampler.end();

sampleWithReplacements

Function returning a random sample of size k with replacements from the given array. This prosaically means that an items from the array might occur several times in the resulting sample.

The function runs in both O(k) time & space complexity.

import sampleWithReplacements from 'pandemonium/sample-with-replacements';
// Or
import {sampleWithReplacements} from 'pandemonium';

sampleWithReplacements(3, ['apple', 'orange', 'pear', 'pineapple']);
>>> ['apple', 'pear', 'apple']

// To create your own function using custom RNG
import {createSampleWithReplacements} from 'pandemonium/sample-with-replacements';

const customSample = createSampleWithReplacements(rng);

samplePairs

Function returning a random sample of k unique unordered pairs from the given array.

It works by storing a unique key created from the picked pairs, making it a specialized variant of naiveSample.

It is usually quite efficient because when sampling pairs, the total size of the population, being combinatorial, is often magnitudes larger than the size of the sample we need to retrieve.

Note finally that this function is able to sample pairs of indices without requiring you to represent the range of indices in memory.

import samplePairs from 'pandemonium/sample-pairs';
// Or
import {samplePairs} from 'pandemonium';

samplePairs(2, ['apple', 'orange', 'pear', 'pineapple']);
>>>  [['apple', 'pear'], ['orange', 'pear']]

// Alternatively, you can pass a length and get a sample of pairs of indices
samplePairs(2, 4);
>>> [[0, 2], [1, 2]]

// To create your own function using custom RNG
import {createSamplePairs} from 'pandemonium/sample-pairs';

const customSamplePairs = createSamplePairs(rng);

sampleOrderedPairs

Function returning a random sample of k unique ordered pairs from the given array.

It works by storing a unique key created from the picked pairs, making it a specialized variant of naiveSample.

It is usually quite efficient because when sampling pairs, the total size of the population, being combinatorial, is often magnitudes larger than the size of the sample we need to retrieve.

Note finally that this function is able to sample pairs of indices without requiring you to represent the range of indices in memory.

import sampleOrderedPairs from 'pandemonium/sample-pairs';
// Or
import {sampleOrderedPairs} from 'pandemonium';

sampleOrderedPairs(2, ['apple', 'orange', 'pear', 'pineapple']);
>>>  [['apple', 'pear'], ['pear', 'orange']]

// Alternatively, you can pass a length and get a sample of pairs of indices
sampleOrderedPairs(2, 4);
>>> [[0, 2], [2, 1]]

// To create your own function using custom RNG
import {createSampleOrderedPairs} from 'pandemonium/sample-ordered-pairs';

const customSampleOrderedPairs = createSampleOrderedPairs(rng);

weightedReservoirSample

Function returning a random sample of size k from a given array of weighted items.

The result is a sample without replacement, which, in the case of weighted items, has been chosen to mean that subsequent items are picked based on the proportional total weight of the remaining items.

We use algorithm "A-ES" from the following papers:

Pavlos S. Efraimidis, Paul G. Spirakis. "Weighted random sampling with a reservoir." https://arxiv.org/pdf/1012.0256.pdf

Pavlos S. Efraimidis. "Weighted Random Sampling over Data Streams."

This function runs in O(n) time and O(k) memory.

A helper class working able to work on an arbitrary stream of data that does not need to fit into memory is also available if you need it.

import weightedReservoirSample from 'pandemonium/weighted-reservoir-sample';
// Or
import {weightedReservoirSample} from 'pandemonium';

weightedReservoirSample(2, [.1, .1, .4, .3, .05]);
>>> [.3, .4]

// To create your own function using custom RNG
import {createWeightedReservoirSample} from 'pandemonium/weighted-reservoir-sample';

const customWeightedReservoirSample = createWeightedReservoirSample(rng);

// To sample arbitrary items
const data = [{label: 'orange', importance: 34}, ...];

const customWeightedReservoirSample = createWeightedReservoirSample({
  getWeight: item => item.importance
});

// To use the helper class
import {WeightedReservoirSampler} from 'pandemonium/weighted-reservoir-sample';

// If RNG is not provided, will default to Math.random
const sampler = new WeightedReservoirSampler(10, {rng, getWeight});

for (const value of lazyIterable) {
  sampler.process(value);
}

// To retrieve the sample once every value has been consumed
const sample = sampler.end();

Contribution

Contributions are obviously welcome. Please be sure to lint the code & add the relevant unit tests before submitting any PR.

git clone [email protected]:Yomguithereal/pandemonium.git
cd pandemonium
npm install

# To lint the code
npm run lint

# To run the unit tests
npm test

License

MIT

More Repositories

1

react-blessed

A react renderer for blessed.
JavaScript
4,440
star
2

baobab

JavaScript & TypeScript persistent and optionally immutable data tree with cursors.
JavaScript
3,148
star
3

mnemonist

Curated collection of data structures for the JavaScript/TypeScript language.
JavaScript
2,261
star
4

talisman

Straightforward fuzzy matching, information retrieval and NLP building blocks for JavaScript.
JavaScript
700
star
5

baobab-react

React integration for Baobab.
JavaScript
310
star
6

kotatsu

Straightforward command line tool to setup a development environment for modern JavaScript.
JavaScript
261
star
7

clj-fuzzy

A handy collection of algorithms dealing with fuzzy strings and phonetics.
Clojure
260
star
8

obliterator

Higher order iterator library for JavaScript and TypeScript.
JavaScript
53
star
9

mtgnode

A realtime web application for Magic the Gathering.
JavaScript
49
star
10

gexf

Gexf library for JavaScript
JavaScript
34
star
11

decypher

A handful of cypher utilities for Node.js
JavaScript
33
star
12

fog

A fuzzy matching & clustering library for python.
Python
25
star
13

colback

JavaScript asynchronous paradigm shift in the blink of an eye.
JavaScript
17
star
14

dolman

Light express app wrapper to develop an API comfortably.
JavaScript
16
star
15

vimeo-srt

A simplistic jQuery plugin to display srt subtitles along with an embedded vimeo video.
JavaScript
10
star
16

furuikeya

Procedural Haiku generation with Twitter API 1.1
Python
10
star
17

mtgparser

A compilation of handy parsers for popular Magic the Gathering deck formats.
JavaScript
9
star
18

agent-smith

Simple neo4jmyadmin powered by sigma.js
JavaScript
8
star
19

courses

Miscellaneous pages needing to be served.
CSS
8
star
20

takoyaki

Fuzzy clustering interface prototype.
JavaScript
7
star
21

recettes

Livre de recettes en format Markdown.
7
star
22

djax-client

A straightforward services client powered by djax.
JavaScript
7
star
23

ebbe

Collection of typical helper functions for python.
Python
6
star
24

deku-hmr-example

Simple example of HMR setup for deku.
JavaScript
5
star
25

sigma-experiments

Various experiments related to sigma v2.
TypeScript
5
star
26

clj-cmudict

Clojure wrapper for the CMU Pronouncing Dictionary.
Clojure
5
star
27

rhetorical

JavaScript library dealing with figures of speech, word play and literature.
JavaScript
4
star
28

colifrapy

Command Line Framework for Python
Python
4
star
29

yomguithereal.github.io

A blog.
HTML
4
star
30

levenshtein-lte1

A very fast JavaScript implementation of Levenshtein distance for the k <= 1 case.
JavaScript
3
star
31

helpers

Miscellaneous helper functions for JavaScript.
JavaScript
3
star
32

sabretache

A javascript library to discover similarities in html documents.
JavaScript
2
star
33

react-utilities

Some helpful utilities to work with React.
JavaScript
2
star
34

sigma-visualizer

A minimalist sigma usage.
JavaScript
2
star
35

plickle

Create, parse and execute Gherkin-like DSLs quick and easy.
JavaScript
2
star
36

baobab-deku

Simple helpers to use Baobab along with deku
JavaScript
2
star
37

StreamlineD3

Providing developers with a simple way to create dynamic D3.js visualizations with live data.
JavaScript
2
star
38

phylactery

Curated collection of data structures for Python.
Python
2
star
39

eslint-config

Just an eslint config.
JavaScript
1
star
40

npm-gexf-dependencies

Basic tool for converting the results of npm ls --json into a gexf file.
JavaScript
1
star
41

modular

Some files linked to modular synths.
1
star
42

sandcrawler-logger

A logger plugin for sandcrawler.
JavaScript
1
star
43

Yomguithereal

1
star
44

special-agent

Thin wrapper around a compilation of common user agent strings that one can query easily through tags.
JavaScript
1
star
45

python-daj

Read and write data without further ado.
Python
1
star
46

persil

Threadsafe & persistent python collections relying on SQLite.
Python
1
star
47

scuttlebutt-sigma

An attempt at visualizing scuttlebutt networks using sigma.js.
JavaScript
1
star
48

symlarjs

calculate and verify similarity between strings
JavaScript
1
star
49

afscrap

Aufeminin.com scraper for social researches.
JavaScript
1
star