Front-end Algorithms - Tips to reduce if-else
1. Short circuit operation
The logic of Javascript or the short-circuit operation of || can sometimes be used to replace some relatively simple if else
Short-circuit operation of logical or ||: If the left side can be turned into true, return the value of the left formula, otherwise return the value of the right formula. Let's use a simple case to express:
let c
if(a){
c = a
} else {
c = b
}
Short circuit algorithm simplified:
let c = a || b
2. Ternary operator
In many cases, we can use ternary operators to replace if else for simple judgments. Only one layer of ternary operators is recommended here, because multi-layer nested ternary operators are not very readable.
Example: Return 1 if the condition is true, otherwise return 0:
const fn = (nBoolean) {
if (nBoolean) {
return 1
} else {
return 0
}
}
// use ternary operator
const fn = (nBoolean) {
return nBoolean ? 1 : 0
}
Ternary operators are also used in many places, such as: conditional assignment, recursion...
// num value is 10 when nBoolean is true, otherwise it is 5
let num = nBoolean ? 10 : 5
// Find the sum of integers between 0-n
let sum = 0;
function add(n){
sum += n
return n >= 2 ? add(n - 1) : result;
};
let num = add(10);//55
3. Switch case
The above two methods: short-circuit operation and ternary operation are very useful, and the code is very concise, but they can only be used for simple judgments, and cannot be used when encountering multiple conditions. For switch case, although its readability is indeed higher than else if, but writing is more troublesome, there are advantages and disadvantages
Example: There are four types of A, B, C, and D. When A and B are used, output 1, C outputs 2, D outputs 3, and the default output is 0.
let type = 'A'
//if else if
if (type === 'A' || type === 'B') {
console.log(1);
} else if (type === 'C') {
console.log(2);
} else if(type === 'D') {
console.log(3);
} else {
console.log(0)
}
//switch case
switch (type) {
case 'A':
case 'B':
console.log(1)
break
case 'C':
console.log(2)
break
case 'D':
console.log(3);
break;
default:
console.log(0)
}
4. Object Configuration/Strategy Pattern
Object configuration looks similar to the strategy pattern, which uses different data/algorithms/functions according to different parameters.
The strategy pattern is to encapsulate a series of algorithms and make them replaceable with each other. The encapsulated algorithm is independent, and its characteristics cannot be changed externally.
The object configuration method implements the above example:
let type = 'A'
let tactics = {
'A': 1,
'B': 1,
'C': 2,
'D': 3,
default: 0
}
console.log(tactics[type]) // 1
Example2:
Different discounts are used according to different users, such as: no discount for ordinary users, 10% discount for ordinary member users, 15% discount for annual fee members, 20% discount for super members
Use if else to implement:
const getDiscount = (userKey) => {
if (userKey === 'ordinary member') {
return 0.9
} else if (userKey === 'annual membership') {
return 0.85
} else if (userKey === 'super member') {
return 0.8
} else {
return 1
}
}
console.log(getDiscount('ordinary member')) // 0.9
Implemented using the Object Configuration/Strategy pattern
const getDiscount = (userKey) => {
// We can generate our discount object based on user type
let discounts = {
'Normal Member': 0.9,
'Annual membership': 0.85,
'Super Member': 0.8,
'default': 1
}
return discounts[userKey] || discounts['default']
}
console.log(getDiscount('ordinary member')) // 0.9
5. Using the Map keyword
Object configuration does not necessarily have to use objects to manage our key-value pairs, you can alsouse Map to manage
const getDiscount = (userKey) => {
// We can generate our discount object based on user type
let discounts = new Map([
['ordinary member', 0.9],
['Annual membership', 0.85],
['super member', 0.8],
['default', 1]
])
return discounts.get(userKey) || discounts.get('default')
}
console.log(getDiscount('ordinary member')) // 0.9
Case 2 Year-end bonus:
The company's year-end bonus is issued according to the employee's salary base and performance level. For example, the year-end bonus for those with performance A is 4 times the salary, for those with performance B, it is 3 times, and for those with performance C, it is only 2 times. Adding a division of departments, assuming that the company has two departments D and F, the performance of D department is better, so the year-end bonus is doubled by 1.2 times, and the performance of F department is poor, and the year-end bonus is 10% off
let strategies = new Map([
['A_D', 4 * 1.2],
['B_D', 3 * 1.2],
['C_D', 2 * 1.2],
['A_F', 4 * 0.9],
['B_F', 3 * 0.9],
['C_F', 2 * 0.9]
])
const calculateBonus = (performanceLevel, salary, department) => {
return strategies. get(`${performanceLevel}_${department}`) * salary
}
calculateBonus( 'A', 20000, 'D' ) // output: 96000