简体   繁体   中英

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

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;
}
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).

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

Mb I will refactor this code like this but it's not really standard patter :

var incomingValue=0.08; // Set by an API
var setValueName;
var setValueIcon;

switch(true) {
    case incomingValue < 0.10 :
        setValueName = "something"; 
        setValueIcon ="something.png";
        alert("Hello World !");
        break;
    case incomingValue > 0.09 && incomingValue < 0.20 :
        setValueName = "somethingElse"; 
        setValueIcon ="somethingElse.png";
        alert("Hello !");
        break;
    default :
        alert("Adele !");
        break;
}

The mortal will use the if...else if... condition like this :

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

But I dont like this way...My opinion :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM