Public
Edited
Apr 29
Insert cell
Insert cell
Insert cell
data = {
button;
return Array.from({ length: 10_000 }, () => _.random(0, 9));
}
Insert cell
Insert cell
Insert cell
new Counter(data)
Insert cell
Insert cell
{
const c = new Counter();
for (let value of data) {
c.increment(value);
}
return c;
}
Insert cell
Insert cell
counter = {
const c = new Counter();
for (let value of data) {
c[value] += 1;
}
return c;
}
Insert cell
Insert cell
[...counter.mostCommon({ n: 3 })]
Insert cell
Insert cell
[...counter.leastCommon({ normalize: true })]
Insert cell
Insert cell
[...counter.sorted({ normalize: true })]
Insert cell
[...counter]
Insert cell
Insert cell
Plot.plot({
width: 300,
height: 150,
y: { nice: true },
marks: [Plot.barY(counter, { x: (d) => d[0], y: (d) => d[1] })]
})
Insert cell
class Counter extends Map {
constructor(iterable = []) {
super();

// If an iterable is given, count each element
for (const item of iterable) {
this.increment(item);
}

// Create a proxy to allow using bracket notation
return new Proxy(this, {
get: (target, prop) => {
// Return method if it exists on the object
if (typeof target[prop] === "function") {
return target[prop].bind(target);
}

if (prop in target) {
return target[prop];
}

// For number-like strings, convert to number to maintain key type
const key =
!isNaN(prop) && String(Number(prop)) === prop ? Number(prop) : prop;

// For other properties, return the count (or 0)
return target.get(key) || 0;
},

set: (target, prop, value) => {
// Convert number strings to actual numbers for consistency
const key =
!isNaN(prop) && String(Number(prop)) === prop ? Number(prop) : prop;

// Set the count using Map's set method
target.set(key, value);
return true;
}
});
}

// Get with default 0 for missing keys
get(key) {
return super.get(key) || 0;
}

// Increment a count
increment(key, count = 1) {
this.set(key, this.get(key) + count);
return this;
}

// Get the most common items
mostCommon({ n = null, normalize = false } = {}) {
return this.sorted({ n, normalize, compare: (a, b) => b[1] - a[1] });
}

// Get the least common items
leastCommon({ n = null, normalize = false } = {}) {
return this.sorted({ n, normalize, compare: (a, b) => a[1] - b[1] });
}

// Get in sorted order
sorted({
n = null,
normalize = false,
compare = (a, b) => a[0] - b[0]
} = {}) {
let entries = [...this];
entries.sort(compare);

if (n !== null) {
entries = entries.slice(0, n);
}

if (normalize) {
const total = this.total();
return entries.map(([a, b]) => [a, b / total]);
} else {
return entries;
}
}

// Get the total of all counts
total() {
let sum = 0;
for (const count of this.values()) {
sum += count;
}
return sum;
}
}
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