0
\$\begingroup\$

I have an interesting problem to solve and despite having a running solution, I was wondering where I could improve it.

In a range from 1 to 1000, I want to create an array with different increments according to the current interval. So, from 1.0 to 2.0, the increment should be 0.01, from 2.0 to 4.0 it should be 0.02, and so on. There are many intervals. The final result yields an array with 350 fields.

I've come up with a super basic, easy to implement solution using ifs. So it goes something like:

// In one file I have:
const grid = new Grid().buildGrid();
console.log(grid); // And expect a grid which respects the rules defined in the below class.

// Grid Class:
class Grid {
    constructor() {
        this.array = [];
    }

buildGrid() {
    _createKeysWithTicks(this.array);
}

_createKeysWithTicks(array){
    let i = 1.0;
    while (i < 1000){
        i = parseFloat((i + findStepSize(i)).toFixed(2));
            array.push(i);
    }
    return array;
}

findStepSize(number) {
    let res;
    if (number >= 1.0 && number < 2.0) {
        res = 0.01;
    } else if (number >= 2.0 && number < 4.0) {
        res = 0.02;
    } else if (number >= 4.0 && number < 5.0) {
        res = 0.1;
    } else if (number >= 5.0 && number < 10.0) {
        res = 0.5;
    } else if (number >= 10.0 && number < 50.0) {
        res = 1.0;
    } else if (number >= 50.0 && number < 100.0) {
        res = 10;
    }

    return res;
}

However, this is not elegant, at all because I get numerous if statements. I could swap for a switch statement, thus reducing the number of comparisons, which is nice. But does it improve performance?

The suggestion is:

findStepSize(i) {
    let res;
    switch (number):
        case(number >= 1.0 && number < 2.0) {
            res = 0.01;
            break;
        case(number >= 2.0 && number < 4.0) {
            res = 0.02;
            break;
        case(number >= 4.0 && number < 5.0) {
            res = 0.1;
            break;
        case(number >= 5.0 && number < 10.0) {
            res = 0.5;
            break;
        case(number >= 10.0 && number < 50.0) {
            res = 1.0;
            break;
        case(number >= 50.0 && number < 100.0) {
            res = 10;
            break;
    }
    return res;
}

The increments are not linear, otherwise the solution could be different.

How would you optimize or clean this code?

Note: I understand and respect the rules of this community and I appreciate your feedback. Unfortunately, I cannot disclose much more details. If this is still not sufficient for you to think of how would you get rid of those If statements, I can't help much more because I can't simply provide more details. In fact, the data above is random and it's not the use case.

\$\endgroup\$
  • \$\begingroup\$ Is the real purpose of this for labelling the axes of a plot or chart? If that's the case, it might make a better basis for the question title, to give a high-level overview of the objective. \$\endgroup\$ – Toby Speight Oct 22 '18 at 10:47
  • \$\begingroup\$ No, it's not. The goal is built a sports betting grid so I can use those values in another place. However, those are business rules and seems a good option to have this part independent of the rest of the code so that if the rules change we only need to modify one single file/class. \$\endgroup\$ – Gustavo Silva Oct 22 '18 at 10:55
  • 1
    \$\begingroup\$ Please put actually functional code that reviewers can run... not snippets from inside a class. \$\endgroup\$ – FreezePhoenix Oct 22 '18 at 12:15
  • 1
    \$\begingroup\$ @GustavoSilva So, you are creating an array of Floats? And the array is: 1.01, 1.02, 1.03, ... 1.98, 1.99, 2.00, 2.02, 2.04, 2.06, ... 3.96, 3.98, 4.00, 4.1, 4.2, 4.3, ... 4.8, 4.9, 5.0, 5.5, 6.0, 6.5, ... 9.5, 10.0, 20.0, 30.0, ... 980.0, 990.0, 1000.0? Is that correct? So, 355 items in your array? (1.01-2.0 is 100 items. 2.02-4.0: 100 items. 4.1-5.0: 10 items. 5.5-10.0: 10 items. 11.0-50.0: 40 items. 60.0-1000.0: 95 items. 100+100+10+10+40+95: 355 items. Is that correct? \$\endgroup\$ – Zonker.in.Geneva Oct 24 '18 at 13:07
  • 1
    \$\begingroup\$ For this example, that's correct, yes. \$\endgroup\$ – Gustavo Silva Oct 24 '18 at 13:08
1
\$\begingroup\$

You can take advantage of the fact that you're iterating in increasing order, i.e. the trivial fact that if a number is greater than n, then it's also greater than any number below n; thus you can just keep track of the latest threshold you passed and only check if you've reached the next one.

let thresholds = [2, 4, 5, 10, 50, 100, 1000];
let increments = [0.01, 0.02, 0.1, 0.5, 1, 10];
let p = 0;

function createKeysWithTicks(array) {
    let i = 1.0;
    while (i < 1000) {
        array.push(Number(i.toFixed(2)));
        i += increments[p];
        if (i >= thresholds[p]) {
            p++;
        }
    }
 }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.