rank.js 942 B

123456789101112131415161718192021222324
  1. import ascending from "./ascending.js";
  2. import {ascendingDefined, compareDefined} from "./sort.js";
  3. export default function rank(values, valueof = ascending) {
  4. if (typeof values[Symbol.iterator] !== "function") throw new TypeError("values is not iterable");
  5. let V = Array.from(values);
  6. const R = new Float64Array(V.length);
  7. if (valueof.length !== 2) V = V.map(valueof), valueof = ascending;
  8. const compareIndex = (i, j) => valueof(V[i], V[j]);
  9. let k, r;
  10. values = Uint32Array.from(V, (_, i) => i);
  11. // Risky chaining due to Safari 14 https://github.com/d3/d3-array/issues/123
  12. values.sort(valueof === ascending ? (i, j) => ascendingDefined(V[i], V[j]) : compareDefined(compareIndex));
  13. values.forEach((j, i) => {
  14. const c = compareIndex(j, k === undefined ? j : k);
  15. if (c >= 0) {
  16. if (k === undefined || c > 0) k = j, r = i;
  17. R[j] = r;
  18. } else {
  19. R[j] = NaN;
  20. }
  21. });
  22. return R;
  23. }