UNPKG

newrelic

Version:
64 lines (54 loc) 1.69 kB
/* * Copyright 2020 New Relic Corporation. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ 'use strict' // from http://en.wikipedia.org/wiki/Reservoir_sampling function Reservoir(limit) { this.limit = limit || 10 this.seen = 0 this._data = [] } Reservoir.prototype.overflow = function overflow() { const diff = this.seen - this.limit return diff >= 0 ? diff : 0 } Reservoir.prototype.add = function add(item) { if (this.seen < this.limit) { this._data.push(item) } else { // Take a number between 0 and n + 1, drop the element at that index // from the array. If the element to drop is the (n + 1)th, the new item is // not added, otherwise the new item replaces the item that was // dropped. // This is effectively the same as adding the new element to the // end, swapping the last element (the new one) with a random element in the list, // then dropping the last element (the potentially swapped one) in the list. const toReplace = Math.floor(Math.random() * (this.seen + 2)) // eslint-disable-line sonarjs/pseudo-random if (toReplace < this.limit) { this._data[toReplace] = item } } this.seen++ } Reservoir.prototype.toArray = function toArray() { return this._data } Reservoir.prototype.merge = function merge(items) { if (!items || !items.length) { return } if (items === this._data) { return } for (let i = 0; i < items.length; i++) { this.add(items[i]) } } Reservoir.prototype.setLimit = function setLimit(newLimit) { this.limit = newLimit if (this._data.length > newLimit) { this._data = this._data.slice(0, newLimit) } } module.exports = Reservoir