Skip to content

Commit

Permalink
Merge pull request #365 from devoxa/percentile
Browse files Browse the repository at this point in the history
Add percentile function
  • Loading branch information
kodiakhq[bot] authored Aug 5, 2022
2 parents 0d07112 + 78e50ab commit 1077c50
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 0 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,17 @@ flocky.omit(object, ['a'])

<sup>[Source](./src/omit/omit.ts)[Benchmark](./src/omit/BENCHMARK.md) • Minify: 143 B • Minify & GZIP: 129 B<sup>

### percentile(array, k)

Compute the kth percentile of the values in an array.

```js
flocky.percentile([90, 85, 65, 72, 82, 96, 70, 79, 68, 84], 0.9)
// -> 90.6
```

<sup>[Source](./src/percentile/percentile.ts) • Minify: 217 B • Minify & GZIP: 156 B<sup>

### pick(object, keys)

Create an object composed of the specified `keys`.
Expand Down
4 changes: 4 additions & 0 deletions src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ describe('index file', () => {
it('exports the modules', () => {
expect(Object.keys(flocky).length).toBeGreaterThanOrEqual(5)
})

it('exports custom errors', () => {
expect(new _flocky.PromiseTimeoutError()).toBeInstanceOf(Error)
})
})

describe('documentation examples', () => {
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export { min } from './min/min'
export { omit } from './omit/omit'
export { pick } from './pick/pick'
export { promisePool } from './promisePool/promisePool'
export { percentile } from './percentile/percentile'
export { promiseTimeout, PromiseTimeoutError } from './promiseTimeout/promiseTimeout'
export { random } from './random/random'
export { randomString } from './randomString/randomString'
Expand Down
28 changes: 28 additions & 0 deletions src/percentile/percentile.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { percentile } from './percentile'

describe('percentile', () => {
it('calculates the percentile of an array of numbers', () => {
expect(percentile([1, 4, 2, 4, 0], 0.5)).toEqual(2)

const values = [90, 85, 65, 72, 82, 96, 70, 79, 68, 84]
expect(percentile(values, 1)).toEqual(96)
expect(percentile(values, 0.95)).toEqual(93.3)
expect(percentile(values, 0.9)).toEqual(90.6)
expect(percentile(values, 0.8)).toEqual(86)
expect(percentile(values, 0.75)).toEqual(84.75)
expect(percentile(values, 0.7)).toEqual(84.3)
expect(percentile(values, 0.6)).toEqual(82.8)
expect(percentile(values, 0.5)).toEqual(80.5)
expect(percentile(values, 0.25)).toEqual(70.5)
expect(percentile(values, 0)).toEqual(65)

expect(percentile([0], 0.5)).toEqual(0)
expect(percentile([], 0.5)).toEqual(NaN)
})

it('does not mutate the input', () => {
const input = [3, 1, 2, 3]
percentile(input, 0.5)
expect(input).toEqual([3, 1, 2, 3])
})
})
27 changes: 27 additions & 0 deletions src/percentile/percentile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* ### percentile(array, k)
*
* Compute the kth percentile of the values in an array.
*
* ```js
* flocky.percentile([90, 85, 65, 72, 82, 96, 70, 79, 68, 84], 0.9)
* // -> 90.6
* ```
*/

export function percentile(array: Array<number>, k: number): number {
const values = Array.from(array).sort((a, b) => a - b)
const position = (values.length - 1) * k
const baseIndex = Math.floor(position)

if (values[baseIndex] === undefined) {
return NaN
}

if (values[baseIndex + 1] === undefined) {
return values[baseIndex]
}

const restPosition = position - baseIndex
return values[baseIndex] + (values[baseIndex + 1] - values[baseIndex]) * restPosition
}

0 comments on commit 1077c50

Please sign in to comment.