56 lines
1.9 KiB
TypeScript
56 lines
1.9 KiB
TypeScript
import { isArray, sum } from '@robonen/stdlib';
|
|
import { computed, toValue } from 'vue';
|
|
import type { ComputedRef, MaybeRefOrGetter } from 'vue';
|
|
import type { MaybeComputedRefArgs } from '@/types';
|
|
|
|
/**
|
|
* @name useAverage
|
|
* @category Math
|
|
* @description Reactively compute the average (arithmetic mean) of the provided
|
|
* numbers. Accepts either a variadic list of numbers (each a ref, getter, or raw
|
|
* value) or a single reactive array whose items may themselves be refs/getters.
|
|
* Returns `NaN` when there are no values, mirroring `0 / 0`.
|
|
*
|
|
* @param {...MaybeRefOrGetter<number>} args The values to average, or a single reactive array of values
|
|
* @returns {ComputedRef<number>} A computed ref of the mean (`NaN` when empty)
|
|
*
|
|
* @example
|
|
* const a = ref(1);
|
|
* const b = ref(3);
|
|
* const avg = useAverage(a, b, 2); // 2
|
|
*
|
|
* @example
|
|
* const list = ref([1, 5, 3]);
|
|
* const avg = useAverage(list); // 3
|
|
*
|
|
* @example
|
|
* const list = ref([ref(2), () => 4, 6]);
|
|
* const avg = useAverage(list); // 4
|
|
*
|
|
* @since 0.0.14
|
|
*/
|
|
export function useAverage(array: MaybeRefOrGetter<Array<MaybeRefOrGetter<number>>>): ComputedRef<number>;
|
|
export function useAverage(...args: Array<MaybeRefOrGetter<number>>): ComputedRef<number>;
|
|
export function useAverage(...args: MaybeComputedRefArgs<number>): ComputedRef<number> {
|
|
return computed<number>(() => {
|
|
// Collect into a single flat numeric array so we can reuse stdlib `sum`
|
|
// and divide by the real count in one pass — no intermediate flatMap.
|
|
const values: number[] = [];
|
|
|
|
for (const arg of args) {
|
|
const value = toValue(arg);
|
|
|
|
if (isArray(value)) {
|
|
for (const inner of value)
|
|
values.push(toValue(inner));
|
|
}
|
|
else {
|
|
values.push(value);
|
|
}
|
|
}
|
|
|
|
// Empty -> NaN (0 / 0), matching the mathematical definition of a mean.
|
|
return sum(values) / values.length;
|
|
});
|
|
}
|