I have a numeric range that I want to split in n ranges of equal sizes. Example:
[min, max], n
0, 10, 5 = [[0, 2], [2, 4], [4, 6], [6, 8], [8, 10]]
so I would like to build a function like:
function buckets(range, bucketsNumber) {
const [min, max] = range
const bucketRange = (max - min + 1) / bucketsNumber
const res = _.range(1, bucketsNumber).map((i) => {
const start = (idx) => bucketRange * (idx - 1) + min
const end = start(i) + bucketRange - 1
return [start(i), end]
})
return res
}
The above function doesn't work because buckets([0, 10], 5)
returns:
[
[ 0, 1.2000000000000002 ],
[ 2.2, 3.4000000000000004 ],
[ 4.4, 5.6000000000000005 ],
[ 6.6000000000000005, 7.800000000000001 ]
]
What's wrong with that code?
buckets
should works also with negative range
values..
You don't need lodash for this.
bucket = ([min, max], bucketsNumber) =>
Array.from({length: bucketsNumber}).map((el, idx, arr, step = (max - min) / bucketsNumber) => [min + idx * step, min + (idx + 1) * step])
console.log(0,10,5,bucket([0, 10], 5));
console.log(0,20,4,bucket([0, 20], 4));
console.log(-10,10,2,bucket([-10, 10], 2));
console.log(10,-10,4,bucket([10, -10], 4));
What this does:
[min, max]
in the Arrow Function's parameter list is Array Deconstruction. So min
and max
get the first (index 0
) resp. second element of the parameter arrayArray.from({length: bucketsNumber})
creates an array of length bucketsNumber
min + idx * step
and min + (idx + 1) * step
). min
is taking from the calling function (@cf Closures), idx
is the automatic index of the current element of the array through the map
parameters, and step
is calculated as default parameter in the function parameters (step = (max - min) / bucketsNumber
)