Reputation: 2790
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.
Upvotes: 7
Views: 433
Reputation: 29906
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;
}
Upvotes: 12
Reputation: 102174
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);
Upvotes: 1
Reputation: 115450
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).
Upvotes: 2
Reputation: 479
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 :)
Upvotes: 0