Search code examples
javascriptlodash

Array of ranges from min, max and number of ranges


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..


Solution

  • 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));

    Edit

    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 array
    • Array.from({length: bucketsNumber}) creates an array of length bucketsNumber
      @see Array.from
    • This array will be mapped to a new array which is returned
    • The mapping is done by a function that will return an array of arrays which each habe two numbers (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)