I'm writing a typescript function that accepts a numeric array (i.e., type: number[]
) and calculates its mean. In addition, I want to account for when the input array might contain some null
values. To this end, I added an argument, that when set to true
, tells the function to remove null
s before calculating the mean.
But I can't figure out the proper way to do this, as I can't override the input within the function.
Here's my code for calcMean()
function calcMean(arr: number[], nullRemove: boolean = true): number {
if (nullRemove) { // if TRUE, which is the default, then throw out nulls and re-assign to `arr`
const arr: number[] = arr.filter((elem) => elem !== null);
}
// then simply calculate the mean of `arr`
return arr.reduce((acc, v, i, a) => acc v / a.length, 0); // https://stackoverflow.com/a/62372003/6105259
}
I then get an error:
Block-scoped variable 'arr' used before its declaration.ts(2448)
I also tried using let
in addition or instead of const
but it didn't solve the problem.
What am I missing here?
CodePudding user response:
Two options for you:
1. Don't redeclare it, just reassign it:
function calcMean(arr: number[], nullRemove: boolean = true): number {
if (nullRemove) { // if TRUE, which is the default, then throw out nulls and re-assign to `arr`
arr = arr.filter((elem) => elem !== null);
// ^^^ No `const` here
}
// then simply calculate the mean of `arr`
return arr.reduce((acc, v, i, a) => acc v / a.length, 0); // https://stackoverflow.com/a/62372003/6105259
}
Some folks believe reassigning parameters is poor style (I'm not one of them provided the function is quite small as in your case, but I understand the argument), so alternatively:
2. Assign to a different variable:
function calcMean(arr: number[], nullRemove: boolean = true): number {
// Remove `null` if requested
const a = nullRemove ? arr.filter(elem => elem !== null) : arr;
// then simply calculate the mean of `arr`
return a.reduce((acc, v, i, a) => acc v / a.length, 0); // https://stackoverflow.com/a/62372003/6105259
}
CodePudding user response:
The code in your question doesn't currently allow for null
values to be included in the number[]
parameter.
I like for my code to be explicit about what's happening, so in the case where there might be null
s mixed in the array of number
s, I would explicitly convert them to 0
in the case that they are not removed:
/** Each null element is either omitted or converted to 0 */
function handleNullValues (arr: readonly (number | null)[], omit = true): number[] {
return omit ?
arr.filter((value): value is number => value !== null)
: arr.map(value => value === null ? 0 : value);
}
function calcMean (arr: readonly (number | null)[], nullRemove = true): number {
const numbers = handleNullValues(arr, nullRemove);
return numbers.reduce((sum, n) => sum n) / numbers.length;
}
// Test
console.assert(calcMean([null, 1, 3, 7, 9]) === 5); // ok
console.assert(calcMean([null, 10, 1, 3, 7, 9], false) === 5); // ok