Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I refactor this bunch of if statements?

Imagine that I have a variable called incomingValue and I'm getting a number from an API as it's value. The values are between 0 to 1 and I'm setting two other variables depending on this value using bunch of if statements like you see below.

var incomingValue; // Set by an API
var setValueName;
var setValueIcon;
if (incomingValue < 0.10 ) { 
  setValueName = 'something'; 
  setValueIcon = 'something.png' 
}
if (incomingValue > 0.09 && incomingValue < 0.20 ) { 
  setValueName = 'somethingElse'; 
  setValueIcon = 'somethingElse.png';
}

In the actual implementation, I have around 10 if statements checking for specific intervals up until 1. e.g. do this if it's more than 0.10 but less than 0.16 and so on.

As a JavaScript beginner it feels like this is not the right way to do things even though it gets the job done. How would I refactor this code?

Update: As requested, I'm adding the full set of intervals that are used in the original code. I haven't included the full list before because the intervals don't follow a certain pattern.

  • 0 to 0.09
  • 0.09 to 0.20
  • 0.20 to 0.38
  • 0.38 to 0.48
  • 0.48 to 0.52
  • 0.52 to 0.62
  • 0.61 to 0.80
  • 0.80 to 1
like image 293
cinnaroll45 Avatar asked Sep 25 '16 12:09

cinnaroll45


People also ask

How do you refactor multiple if statements?

So, how do you refactor multiple nested if statements? The easiest possible way is to use guard clauses. A guard clause is an if statement that checks for a condition and favors early exit from the current method. If the condition is satisfied, the if block returns from the method.


3 Answers

Remember the single responsibility principle. Take that code out to a separate function like so:

function determineNameAndIcon(incomingValue) {
  if (incomingValue < 0.10) { 
    return { 
      name: "something",
      icon: "something.png"
    };
  }
  if (incomingValue < 0.20) { 
    return {
      name: "somethingElse",
      icon: "somethingElse.png"
    };
  }
  // etc
  return {
    name: "somethingDefault",
    icon: "somethingDefault.png"
  };
}

// ...

var incomingValue; // Set by an API
const {
  name: setValueName,
  icon: setValueIcon
} = determineNameAndIcon(incomingValue);

Notice that determineNameAndIcon is still a very long function with repeating parts. This can be further refactored to a data-driven version:

const nameAndIconList = [
  {
    maxValue: 0.10,
    name: "something",
    icon: "something.png"
  },
  {
    maxValue: 0.20,
    name: "somethingElse",
    icon: "somethingElse.png"
  },
  // ...
];

const nameAndIconDefault = {
  name: "somethingDefault",
  icon: "somethingDefault.png"
};

function determineNameAndIcon(incomingValue) {
  for (let item of nameAndIconList) {
    if (incomingValue < item.maxValue) {
      return item;
    }
  }
  return nameAndIconDefault;
}
like image 71
Tamas Hegedus Avatar answered Oct 25 '22 19:10

Tamas Hegedus


function findValue(incomingValue){

    var itemValues = [
      [.06, "valueName", "valueIcon"],  
      [.08, "valueName", "valueIcon"],
      [.09, "valueName", "valueIcon"],
      [.1, "valueName", "valueIcon"],

    ]


  var foundValues = itemValues.
        filter(v=>v[0] >= incomingValue)
        .sort();

  if(foundValues.length == 0){
     throw "incoming value not found."
  } 
  return foundValues[0];
}

let value = findValue(.079);

console.log( value );

This is assuming that you want the lowest portion of the range to be the one selected (just reverse the sort if you want it to be the highest).

like image 23
kemiller2002 Avatar answered Oct 25 '22 18:10

kemiller2002


A solution using an array where you set the ranges for your results:

var categories = [{something: [0, 0.1]}, 
                  {somethingElse: [0.1, 0.2]}, 
                  {somethingElse2: [0.2, 0.3]}, 
                  {anotherSomething: [0.3, 1]}];

function res(number){ return Object.keys(categories.filter(function(elem) {
  var key = elem[Object.keys(elem)];
  return number >= key[0] && number < key[1]
})[0])[0]};

var incomingValue = 0.12;

var setValueName = res(incomingValue);
var setValueIcon = res(incomingValue) + ".png";
console.log(setValueName, setValueIcon);
like image 31
Gerardo Furtado Avatar answered Oct 25 '22 18:10

Gerardo Furtado