From f9af4675adc767c3de890e8e20252fdd44e7caf8 Mon Sep 17 00:00:00 2001 From: Jev Forsberg <46619047+baldm0mma@users.noreply.github.com> Date: Wed, 17 Apr 2024 07:01:13 -0600 Subject: [PATCH] Reducers: Update percentile logic - move percentiles to after standard reducers (#86004) * baldm0mma/pth_fix2/ move percentiles to after standard reducers * baldm0mma/pth_fix2/ update ordinal suffix --------- Co-authored-by: nmarrs --- .../src/transformations/fieldReducer.test.ts | 12 +++--- .../src/transformations/fieldReducer.ts | 37 +++++++++++-------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/packages/grafana-data/src/transformations/fieldReducer.test.ts b/packages/grafana-data/src/transformations/fieldReducer.test.ts index 7ccda4c1573..f155a62e511 100644 --- a/packages/grafana-data/src/transformations/fieldReducer.test.ts +++ b/packages/grafana-data/src/transformations/fieldReducer.test.ts @@ -252,17 +252,19 @@ describe('Stats Calculators', () => { expect(reduce(someNulls, ReducerID.count)).toEqual(4); }); - for (let i = 1; i < 100; i++) { - it(`can reduce the ${i}th percentile`, () => { + it('can reduce to percentiles', () => { + // This `Array.from` will build an array of elements from 1 to 99 + const percentiles = [...Array.from({ length: 99 }, (_, i) => i + 1)]; + percentiles.forEach((percentile) => { const preciseStats = reduceField({ field: createField( 'x', Array.from({ length: 101 }, (_, index) => index) ), - reducers: [(ReducerID as Record)[`p${i}`]], + reducers: [(ReducerID as Record)[`p${percentile}`]], }); - expect(preciseStats[`p${i}`]).toEqual(i); + expect(preciseStats[`p${percentile}`]).toEqual(percentile); }); - } + }); }); diff --git a/packages/grafana-data/src/transformations/fieldReducer.ts b/packages/grafana-data/src/transformations/fieldReducer.ts index a08c7db3c50..b3d547184cb 100644 --- a/packages/grafana-data/src/transformations/fieldReducer.ts +++ b/packages/grafana-data/src/transformations/fieldReducer.ts @@ -402,27 +402,34 @@ export const fieldReducers = new Registry(() => [ }), preservesUnits: false, }, + ...buildPercentileReducers(), ]); -for (let i = 1; i < 100; i++) { - const percentile = i / 100; - const id = `p${i}` as ReducerID; +// This `Array.from` will build an array of elements from 1 to 99 +const buildPercentileReducers = (percentiles = [...Array.from({ length: 99 }, (_, i) => i + 1)]) => { + const percentileReducers: FieldReducerInfo[] = []; const nth = (n: number) => n > 3 && n < 21 ? 'th' : n % 10 === 1 ? 'st' : n % 10 === 2 ? 'nd' : n % 10 === 3 ? 'rd' : 'th'; - const name = `${i}${nth(i)} percentile`; - const description = `${i}${nth(i)} percentile value`; - fieldReducers.register({ - id: id, - name: name, - description: description, - standard: false, - reduce: (field: Field, ignoreNulls: boolean, nullAsZero: boolean): FieldCalcs => { - return { [id]: calculatePercentile(field, percentile, ignoreNulls, nullAsZero) }; - }, - preservesUnits: true, + percentiles.forEach((p) => { + const percentile = p / 100; + const id = `p${p}` as ReducerID; + const name = `${p}${nth(p)} %`; + const description = `${p}${nth(p)} percentile value`; + + percentileReducers.push({ + id: id, + name: name, + description: description, + standard: false, + reduce: (field: Field, ignoreNulls: boolean, nullAsZero: boolean): FieldCalcs => { + return { [id]: calculatePercentile(field, percentile, ignoreNulls, nullAsZero) }; + }, + preservesUnits: true, + }); }); -} + return percentileReducers; +}; // Used for test cases export const defaultCalcs: FieldCalcs = {