Skip to content

Commit f005cf8

Browse files
authored
fix quantileIndex (#276)
* fix quantileIndex * don’t invoke accessor more than once
1 parent c62f825 commit f005cf8

3 files changed

Lines changed: 26 additions & 15 deletions

File tree

src/quantile.js

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,16 @@ export function quantileSorted(values, p, valueof = number) {
3232
return value0 + (value1 - value0) * (i - i0);
3333
}
3434

35-
export function quantileIndex(values, p, valueof) {
36-
values = Float64Array.from(numbers(values, valueof));
37-
if (!(n = values.length) || isNaN(p = +p)) return;
38-
if (p <= 0 || n < 2) return minIndex(values);
39-
if (p >= 1) return maxIndex(values);
40-
var n,
41-
i = Math.floor((n - 1) * p),
42-
order = (i, j) => ascendingDefined(values[i], values[j]),
43-
index = quickselect(Uint32Array.from(values, (_, i) => i), i, 0, n - 1, order);
44-
return greatest(index.subarray(0, i + 1), i => values[i]);
35+
export function quantileIndex(values, p, valueof = number) {
36+
if (isNaN(p = +p)) return;
37+
numbers = Float64Array.from(values, (_, i) => number(valueof(values[i], i, values)));
38+
if (p <= 0) return minIndex(numbers);
39+
if (p >= 1) return maxIndex(numbers);
40+
var numbers,
41+
index = Uint32Array.from(values, (_, i) => i),
42+
j = numbers.length - 1,
43+
i = Math.floor(j * p);
44+
quickselect(index, i, 0, j, (i, j) => ascendingDefined(numbers[i], numbers[j]));
45+
i = greatest(index.subarray(0, i + 1), (i) => numbers[i]);
46+
return i >= 0 ? i : -1;
4547
}

test/median-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ it("medianIndex(array) returns the index", () => {
104104
assert.deepStrictEqual(medianIndex([1, 3, 2]), 2);
105105
assert.deepStrictEqual(medianIndex([2, 3, 1]), 0);
106106
assert.deepStrictEqual(medianIndex([1]), 0);
107-
assert.deepStrictEqual(medianIndex([]), undefined);
107+
assert.deepStrictEqual(medianIndex([]), -1);
108108
});
109109

110110

test/quantile-test.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ it("quantileIndex(array, p) returns the index", () => {
9696
assert.deepStrictEqual(quantileIndex([1, 3, 2], 0.2), 0);
9797
assert.deepStrictEqual(quantileIndex([2, 3, 1], 0.2), 2);
9898
assert.deepStrictEqual(quantileIndex([1], 0.2), 0);
99-
assert.deepStrictEqual(quantileIndex([], 0.2), undefined);
99+
assert.deepStrictEqual(quantileIndex([], 0.2), -1);
100100
});
101101

102102
it("quantileIndex(array, 0) returns the minimum index", () => {
@@ -105,16 +105,25 @@ it("quantileIndex(array, 0) returns the minimum index", () => {
105105
assert.deepStrictEqual(quantileIndex([1, 3, 2], 0), 0);
106106
assert.deepStrictEqual(quantileIndex([2, 3, 1], 0), 2);
107107
assert.deepStrictEqual(quantileIndex([1], 0), 0);
108-
assert.deepStrictEqual(quantileIndex([], 0), undefined);
108+
assert.deepStrictEqual(quantileIndex([], 0), -1);
109109
});
110110

111-
it("quantileIndex(array, 1) returns the maxium index", () => {
111+
it("quantileIndex(array, 1) returns the maximum index", () => {
112112
assert.deepStrictEqual(quantileIndex([1, 2], 1), 1);
113113
assert.deepStrictEqual(quantileIndex([1, 2, 3], 1), 2);
114114
assert.deepStrictEqual(quantileIndex([1, 3, 2], 1), 1);
115115
assert.deepStrictEqual(quantileIndex([2, 3, 1], 1), 1);
116116
assert.deepStrictEqual(quantileIndex([1], 1), 0);
117-
assert.deepStrictEqual(quantileIndex([], 1), undefined);
117+
assert.deepStrictEqual(quantileIndex([], 1), -1);
118+
});
119+
120+
it("quantileIndex(array, 0.5) handles undefined values", () => {
121+
assert.deepStrictEqual(quantileIndex([1, 1, 1, null, 2, 3, 3, 3], 0.5), 4);
122+
assert.deepStrictEqual(quantileIndex([1, 1, 1, null, 2, 3, 3, 3], 0.5, (d) => d), 4);
123+
});
124+
125+
it("quantileIndex(array, 0.5) returns the first of equivalent values", () => {
126+
assert.deepStrictEqual(quantileIndex([1, 1, 1, 2, 2, 3, 3, 3], 0.5), 4);
118127
});
119128

120129
function box(value) {

0 commit comments

Comments
 (0)