locutus
Version:
Locutus other languages' standard libraries to JavaScript for fun and educational purposes
65 lines (64 loc) • 2.46 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.mean = mean;
function mean(data) {
// discuss at: https://locutus.io/python/statistics/mean/
// parity verified: Python 3.12
// original by: Kevin van Zonneveld (https://kvz.io)
// note 1: Returns the arithmetic mean and preserves exact integer results when Python does.
// example 1: mean([1, 2, 3])
// returns 1: 2
// example 2: mean([1, 2, 3, 4])
// returns 2: 2.5
// example 3: mean([true, false, true])
// returns 3: 0.6666666666666666
const sequence = toNumericSequence(data, 'mean');
if (sequence.values.length === 0) {
throw new Error('mean requires at least one data point');
}
return statisticsMeanFromSequence(sequence);
}
function toNumericSequence(data, functionName) {
const values = assertStatisticsArray(data, functionName);
return {
values: values.map((value) => toStatisticNumber(value, functionName)),
integral: values.every(isIntegralStatisticValue),
};
}
function statisticsMeanFromSequence(sequence) {
return divideStatisticsValue(sumNumbers(sequence.values), sequence.values.length, sequence.integral);
}
function assertStatisticsArray(data, functionName) {
if (!Array.isArray(data)) {
throw new TypeError(`${functionName}() data must be an array`);
}
return data;
}
function toStatisticNumber(value, functionName) {
if (typeof value === 'number') {
return value;
}
if (typeof value === 'boolean') {
return value ? 1 : 0;
}
if (typeof value === 'bigint') {
const numericValue = Number(value);
if (!Number.isSafeInteger(numericValue)) {
throw new RangeError(`${functionName}() bigint values must fit within JS safe integers`);
}
return numericValue;
}
throw new TypeError(`${functionName}() data must contain only real numbers`);
}
function isIntegralStatisticValue(value) {
return (typeof value === 'boolean' || typeof value === 'bigint' || (typeof value === 'number' && Number.isInteger(value)));
}
function sumNumbers(values) {
return values.reduce((sum, value) => sum + value, 0);
}
function divideStatisticsValue(total, divisor, integral) {
if (integral && Number.isSafeInteger(total) && total % divisor === 0) {
return total / divisor;
}
return total / divisor;
}