function m4(
data,
width,
time = d => d[0],
value = d => d[1]
) {
if (typeof time === 'string') {
const tfield = time;
time = d => d[tfield];
}
if (typeof value === 'string') {
const vfield = value;
value = d => d[vfield];
}
data = Array.isArray(data) ? data : Array.from(data);
const n = data.length;
let tmin = time(data[0]);
let tmax = tmin;
for (let i = 0; i < n; ++i) {
const t = time(data[i]);
if (t < tmin) tmin = t;
if (t > tmax) tmax = t;
}
const delta = tmax - tmin;
const key = t => Math.round(width * (t - tmin) / delta);
const agg = Array(width);
for (let i = 0; i < n; ++i) {
const d = data[i];
const t = time(d);
const v = value(d);
const k = key(t);
if (agg[k] == null) {
agg[k] = {
tmin: t, tmin_i: i,
tmax: t, tmax_i: i,
vmin: v, vmin_i: i,
vmax: v, vmax_i: i,
};
} else {
const a = agg[k];
if (t < a.tmin) { a.tmin = t; a.tmin_i = i; }
if (t > a.tmax) { a.tmax = t; a.tmax_i = i; }
if (v < a.vmin) { a.vmin = v; a.vmin_i = i; }
if (v > a.vmax) { a.vmax = v; a.vmax_i = i; }
}
}
return data.filter((d, i) => {
const t = time(d);
const k = key(t);
const a = agg[k];
return i === a.tmin_i || i === a.tmax_i || i === a.vmin_i || i === a.vmax_i;
});
}