@tanstack/charts
Version:
A chart grammar for TypeScript and JavaScript. Marks consume your data directly, channels describe visual encodings, and the engine compiles them into a renderer-neutral keyed scene. TanStack's compact scales cover common numeric and categorical mappings.
51 lines (50 loc) • 1.68 kB
JavaScript
import {
materializeGroups,
toArray,
transformValues
} from "./transform-internal.js";
function rank(source, options) {
const data = toArray(source);
const values = transformValues(data, options.value);
const outputName = options.as ?? "rank";
assertOutputName(outputName, "rank");
const ranks = /* @__PURE__ */ new Map();
for (const { indexes } of materializeGroups(data, options.by)) {
const direction = options.order === "ascending" ? 1 : -1;
const sorted = indexes.filter((index) => isFiniteNumber(values[index])).sort((left, right) => {
const delta = values[left] - values[right];
return delta === 0 ? left - right : delta * direction;
});
let dense = 0;
let previous;
sorted.forEach((index, position) => {
const value = values[index];
if (previous === void 0 || value !== previous) dense += 1;
const resolved = options.ties === "ordinal" ? position + 1 : options.ties === "dense" ? dense : previous === void 0 || value !== previous ? position + 1 : ranks.get(sorted[position - 1]);
ranks.set(index, resolved);
previous = value;
});
}
return data.flatMap((datum, index) => {
const value = ranks.get(index);
return value === void 0 ? [] : [
{
...datum,
[outputName]: value,
source: [datum],
sourceIndexes: [index]
}
];
});
}
function assertOutputName(name, transform) {
if (name === "source" || name === "sourceIndexes") {
throw new TypeError(`${transform}: output name "${name}" is reserved`);
}
}
function isFiniteNumber(value) {
return typeof value === "number" && Number.isFinite(value);
}
export {
rank
};