Published
Edited
Jun 10, 2022
Importers
21 stars
Insert cell
Insert cell
Insert cell
_identity = function _identity(x) { return x; }
Insert cell
Insert cell
iter = function iter(object) {
if (typeof(object[Symbol.iterator]) === 'function')
return object[Symbol.iterator]();
else if (typeof(object.next) === 'function')
return object; }
Insert cell
Insert cell
range = {
const range_proxy_handler = {
get: function get(obj, prop) {
if (typeof prop == 'symbol') return Reflect.get(obj, prop);
const num = +prop;
if (!Number.isInteger(num)) return Reflect.get(obj, prop);
if ((0 <= num) && (num < obj.length))
return obj.start + obj.step * num;
if ((num < 0) && (num >= -obj.length))
return obj.start + obj.step * (obj.length + num);
return void 0; },
set: function set(obj, prop, value) {
if (typeof prop === 'symbol') return Reflect.set(obj, prop, value);
if (!Number.isInteger(+prop)) {
if (['start', 'stop', 'step', 'length'].indexOf(prop) >= 0)
throw new Error(`Cannot change ${prop} of a range.`);
return Reflect.set(obj, prop, value);
}
throw new Error('Cannot set integer properties on a range.'); },
has: function has(obj, prop) {
if (typeof prop === 'symbol') return Reflect.has(obj, prop);
const num = +prop;
if (!Number.isInteger(num)) return Reflect.has(obj, prop);
return (0 <= num) && (num < obj.length); }}
const range_proto = Object.assign(Object.create(Array.prototype), {
concat: function concat() {
return Array.prototype.concat.call(this, ...arguments); },
includes: function includes(value, from_index=0) {
if (+value !== value) return false;
const k = Math.round((value - this.start) / this.step);
return (from_index <= k) && (k < this.length) &&
(this.start + this.step * k === value); },
indexOf: function indexOf(value, from_index=0) {
if (+value !== value) return -1;
if (from_index < 0) from_index = length + from_index;
const k = Math.round((value - this.start) / this.step);
if ((from_index <= k) && (k < this.length) &&
(this.start + this.step * k === value)) return k;
return -1; },
lastIndexOf: function indexOf(value, from_index) {
if (+value !== value) return -1;
const {length} = this.length
if (from_index == null || from_index >= length) from_index = length - 1;
else if (from_index < 0) from_index = length + from_index;
const k = Math.round((value - this.start) / this.step);
if ((0 <= k) && (k <= from_index) &&
(this.start + this.step * k === value)) return k;
return -1; },
reverse: function reverse() {
this.start = this.start + (this.length - 1)*this.step;
this.step = -this.step;
this.stop = this.start + this.length*this.step;
return this; },
slice: function slice(begin, end) {
const {start, step, length} = this;
begin = (begin == null) ? 0
: (begin < 0) ? length + begin
: (begin > length) ? length : begin;
end = (end == null) ? length
: (end < 0) ? length + end
: (end > length) ? length : end;
if (end < begin) end = begin;
return new Range(start + begin*step, start + end*step, step); },
*[Symbol.iterator]() {
for (let i = 0; i < this.length; i++) yield this.start + i*this.step; },
[Symbol.species]() { return Array; },
[Symbol.toStringTag]: 'Range',
[Symbol.toPrimitive](hint) {
if (hint === 'number') return NaN;
return `Range(${this.start}, ${this.stop}, ${this.step})`; },
[Symbol.isConcatSpreadable]: true });
for (let unsupported_method of [
"copyWithin", "fill", "pop", "push",
"shift", "sort", "splice", "unshift"]) {
range_proto[unsupported_method] = void 0; }
function Range(start, stop, step=1) {
if (stop == null) stop = start, start = 0;
if (!(Number.isInteger(start) && Number.isInteger(stop) && Number.isInteger(step)))
throw new Error(`Range start, stop, and step must be integers.`);
if (step == 0) throw new Error(`Range step cannot be zero.`);
if (!(step > 0 ^ stop < start)) stop = start;
const length = Math.max(0, Math.ceil((stop - start) / step)) | 0;
this.start = start, this.stop = stop, this.step = step, this.length = length;
return new Proxy(this, range_proxy_handler); }
Range.prototype = range_proto;
return function range(start, stop, step=1) {
return new Range(start, stop, step); }; }
Insert cell
Insert cell
linspace = function* linspace(start, stop, n, endpoint=true) {
if (n < 1) throw new Error(`n must be positive.`);
if (n === 1) { yield start; return; }
const ninv = 1 / (n - !!endpoint);
for (let i = 0; i < n; i++) {
const t = i * ninv;
yield start * (1 - t) + stop * t; }}
Insert cell
Insert cell
slice = function* slice(iterable, start, stop, step=1) {
if (stop == null) stop = start, start = 0;
const it = iter(iterable);
consume(it, start);
for (let i = 0, n = stop - start; i < n; i++) {
const {value, done} = it.next(); if (done) return;
if (!(i % step)) yield value; }}
Insert cell
Insert cell
enumerate = function enumerate(iterable, start=0, step=1) {
return zip(count(start, step), iterable); }
Insert cell
Insert cell
map = function* map(callback, ...iterables) {
const iterators = Array.from(iterables, iter);
const n = iterators.length;
while (true) {
const args = Array(iterators.length);
let anydone = 0;
for (let i = 0; i < n; i++) {
const {done, value} = iterators[i].next();
args[i] = value;
anydone |= done; }
if (anydone) break;
yield callback(...args); }}
Insert cell
Insert cell
pluck = function* pluck(property, iterable) {
const iterator = iter(iterable);
while (true) {
const {done, value} = iterator.next(); if (done) break;
yield value[property]; }}
Insert cell
Insert cell
spreadmap = function* spreadmap(callback, iterable) {
for (let args in iterable) yield callback(...args); }
Insert cell
Insert cell
filter = function* filter(predicate, iterable) {
if (predicate == null) predicate = _identity;
for (let item of iterable) if (predicate(item)) yield item; }
Insert cell
Insert cell
filterfalse = function* filterfalse(predicate, iterable) {
if (predicate == null) predicate = _identity;
for (let item of iterable) if (!predicate(item)) yield item; }
Insert cell
Insert cell
compress = {
const select = ([d, s]) => s;
const unzip = ([d, s]) => d;
return function compress(data, selectors) {
return map(unzip, filter(select, zip(data, selectors))); }}
Insert cell
Insert cell
tee = function tee(iterable, n=2) {
const it = iter(iterable)
const buffers = Array.from(range(n), ()=> [])
const gen = function* gen(buffer) {
while (true) {
if (buffer.length == 0) {
const {value, done} = it.next(); if (done) return;
for (let b of buffers) b.push(value); }
yield buffer.shift(); }};
return Array.from(buffers, gen); }
Insert cell
Insert cell
zip = function* zip(...iterables) {
const iterators = Array.from(iterables, iter);
const n = iterators.length;
if (!n) return;
while (true) {
const result = new Array(n);
let anydone = 0;
for (let i = 0; i < n; i++) {
const {done, value} = iterators[i].next();
result[i] = value;
anydone |= done; }
if (anydone) break;
yield result; }}
Insert cell
Insert cell
zip_longest = function*(...iterables) {
const iterators = Array.from(iterables, iter);
const n = iterators.length;
while (true) {
const result = new Array(n);
let alldone = 1;
for (let i = 0; i < n; i++) {
const {done, value} = iterators[i].next();
if (!done) result[i] = value;
alldone &= done; }
if (alldone) break;
yield result; }}
Insert cell
Insert cell
groupby = function* groupby(iterable, key) {
let value, done, curkey, newkey;
if (key == null) key = _identity;
const it = iter(iterable);
({value, done} = it.next()); if (done) return;
curkey = key(value), newkey = curkey;
const grouper = function* grouper() {
while (newkey == curkey) {
yield value;
({value, done} = it.next()); if (done) break;
newkey = key(value); }};
while (true) {
yield [curkey, grouper()]
while (newkey == curkey) {
({value, done} = it.next()); if (done) break;
newkey = key(value); }
if (done) break;
curkey = newkey; }}
Insert cell
Insert cell
all = function all(iterable) {
for (let element of iterable) if (!element) return false;
return true; }
Insert cell
Insert cell
any = function any(iterable) {
for (let element in iterable) if (element) return true;
return false; }
Insert cell
Insert cell
max = function max(iterable, key) {
if (key == null) key = _identity;
let value, done, curkey, largest, largestkey;
const it = iter(iterable);
({value, done} = it.next()); if (done) return;
curkey = key(value), largest = value, largestkey = curkey;
while (true) {
({value, done} = it.next()); if (done) break;
curkey = key(value);
if (curkey > largestkey) largest = value, largestkey = curkey; }
return largest; }
Insert cell
Insert cell
min = function min(iterable, key) {
if (key == null) key = _identity;
let value, done, curkey, smallest, smallestkey;
const it = iter(iterable);
({value, done} = it.next()); if (done) return;
curkey = key(value), smallest = value, smallestkey = curkey;
while (true) {
({value, done} = it.next()); if (done) break;
curkey = key(value);
if (curkey < smallestkey) smallest = value, smallestkey = curkey; }
return smallest; }
Insert cell
Insert cell
reversed = function* reversed(seq) {
for (let n = seq.length, i = n-1; i >= 0; i--) yield seq[i]; }
Insert cell
Insert cell
sorted = {
const compare = function compare (a, b) {
let i, ai, bi, n;
for (i = 2, n = a.length; i < n; ++i) {
if ((bi = b[i]) !== (ai = a[i])) {
if (ai > bi || ai === void 0) return 1;
if (bi > ai || bi === void 0) return -1; } }
return a[1] - b[1]; };
const reverse_compare = function compare (b, a) {
let i, ai, bi, n;
for (i = 2, n = a.length; i < n; ++i) {
if ((bi = b[i]) !== (ai = a[i])) {
if (ai > bi || ai === void 0) return 1;
if (bi > ai || bi === void 0) return -1; } }
return a[1] - b[1]; };
const keywrap = key => (value, index) =>
[value, index].concat(key(value));
const defaultwrap = (value, index) =>
[value, index].concat(value);
const unwrap = (x) => x[0];

return function sorted (iterator, key, reverse) {
const cmp = !reverse ? compare : reverse_compare;
const wrap = (key == null) ? defaultwrap : keywrap(key);
const decorated = Array.from(iterator, wrap).sort(cmp);
for (let i = 0, n = decorated.length; i < n; i++)
decorated[i] = unwrap(decorated[i]); // unwrap in place
return decorated; }; }
Insert cell
Insert cell
reduce = function (callback, iterable, initializer) {
const it = iter(iterable);
let result = initializer;
if (initializer == null) {
const {done, value} = it.next();
if (!done) result = value; }
for (let element of it) result = callback(result, element);
return result; }
Insert cell
Insert cell
sum = {
const add = function (a, b) { return a + b; }
return function sum (iterable, start=0) {
return reduce(add, iterable, start); }; }
Insert cell
Insert cell
accumulate = {
const add = function add(a, b) { return a + b; };
return function* accumulate(iterable, callback) {
if (callback == null) callback = add;
const it = iter(iterable);
const {done, value} = it.next(); if (done) return;
let result = value;
yield value;
for (let element of it) {
result = callback(result, element);
yield result; }}; }
Insert cell
Insert cell
difference = {
const sub = function sub(b, a) { return b - a; };
return function* difference(iterable, callback) {
if (callback == null) callback = sub;
const it = iter(iterable)
const {done, value} = it.next(); if (done) return;
let prev = value;
yield value;
for (let element of it) {
yield callback(element, prev);
prev = element; }}; }
Insert cell
Insert cell
count = function*(start=0, step=1) {
for (let i = start;; i += step) yield i; }
Insert cell
Insert cell
cycle = function*(iterable) {
const saved = new Array;
for (let element of iterable) {
yield element;
saved.push(element); }
if (!saved.length) return;
while (true) for (let element of saved) yield element; }
Insert cell
Insert cell
product = function* product(...iterables) {
const last = iterables.pop();
const remainder = (iterables.length > 0) ? product(...iterables) : [[]];
for (let r of remainder) for (let l of last) yield [...r, l]; }
Insert cell
Insert cell
permutations = function* permutations(iterable, r) {
const pool = [...iterable], n = pool.length;
if (r == null) r = n;
for (let indices of product(...Array(r).fill(range(n)))) {
if (new Set(indices).size == r) {
yield indices.map(i => pool[i]); }}}
Insert cell
Insert cell
combinations = function* combinations(iterable, r) {
const pool = [...iterable], n = pool.length;
for (let indices of permutations(range(n), r))
if (sorted(indices).join() == indices.join())
yield indices.map(i => pool[i]); }
Insert cell
Insert cell
repeat = function* repeat(object, times) {
if (times == null) while (true) yield object;
else for (let i of range(times)) yield object; }
Insert cell
Insert cell
chain = function*(...iterables) {
for (let it of iterables) for (let element of it) yield element; }
Insert cell
Insert cell
chunk = function chunk(iterable, n) {
const args = new Array(n).fill(iter(iterable));
return zip_longest(...args); }
Insert cell
Insert cell
consume = function(iterator, n) {
if (n == null) while (true) {
if (iterator.next().done) break; }
else for (let i = 0; i < n; i++) {
if (iterator.next().done) break; }}
Insert cell
Insert cell
flatten = function flatten (iterable) {
return chain(...iterable); }
Insert cell
Insert cell
take = function take (iterable, n) {
return Array.from(slice(iterable, n)); }
Insert cell
Insert cell
last = function last (iterable, fallback) {
if (iterable.length) return iterable[iterable.length - 1];
const it = iter(iterable);
const {value, done} = it.next(); if (done) return fallback;
let prev_value = value;
while (true) {
const {value, done} = it.next(); if (done) return prev_value;
if (value !== prev_value) prev_value = value; } }
Insert cell
Insert cell
takewhile = function* takewhile(predicate, iterable) {
for (let element of iterable) {
if (predicate(element)) yield element;
else break; }}
Insert cell
Insert cell
dropwhile = function* dropwhile(predicate, iterable) {
const iterator = iter(iterable)
for (let element of iterator) if (!predicate(element)) {
yield element; break; }
yield* iterator; }
Insert cell
Insert cell
spy = function spy(iterable, n=1) {
const it = iter(iterable);
const head = take(it, n);
return [head, chain(head, it)]; }
Insert cell
Insert cell
padded = {
const mod = (a, b) => a - b*Math.floor(a / b);
return function* padded(iterable, fillvalue, n, next_multiple=false) {
if (n == null) {
yield *iterable;
yield *repeat(fillvalue); }
else {
let i = 0;
if (!next_multiple) for (let element of iterable) {
yield element;
if (++i == n) break; }
else for (let element of iterable) {
yield element;
++i; }
yield* repeat(fillvalue, mod(n - i, n)); }}}
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more