我正在尝试简化以下内容:
function handleDirection(src) {
if (src === 'left') {
if (inverse) {
tracker--;
} else {
tracker++;
}
} else {
if (inverse) {
tracker++;
} else {
tracker--;
}
}
}
减少条件数量。 src
始终为'left'
或'right'
。
答案 0 :(得分:49)
您可以检查第一次检查的结果。
这是异或检查。
// typeof inverse === 'boolean'
function handleDirection(src) {
if (src === 'left' === inverse) {
tracker--;
} else {
tracker++;
}
}
检查按(src === 'left') === inverse
的顺序计算表达式:
src === 'left' === inverse
---- first --- returns a boolean value
--------- second --------- take result of former check & compairs it with another boolean
答案 1 :(得分:18)
function handleDirection(src) {
var movement = 1;
if(src === 'left')
movement = -1;
if(inverse)
tracker += movement;
else
tracker -= movement;
}
答案 2 :(得分:11)
您甚至可以只用一行代码来完成它:
function getDirectionOffset(src) {
tracker += (src === 'left' ? 1 : -1) * (inverse ? -1 : 1);
}
答案 3 :(得分:7)
这可以简化为三元表达式,根据状态返回1
或-1
。然后,您可以将其添加到tracker
。
function handleDirection(src) {
var delta = (src === 'left' && inverse) || (src !== 'left' && !inverse) ? -1 : 1;
tracker += delta;
}
然后可以使用@NinaScholz在回答中指出的逻辑进一步简化此操作:
function handleDirection(src) {
var delta = (src === 'left') === inverse ? -1 : 1;
tracker += delta;
}
答案 4 :(得分:4)
假设inverse
是您一次设置的标志,那么您不必每次都考虑它,就可以计算一次它的影响一次并将其用作是的,这将减少您的代码分支和逻辑。如果要随时进行更改,则可能需要分离计算逻辑,以便重新使用它。
然后,您还可以将移动方向提取到一个独立的函数中,您的handleDirection
变得非常简单-您可以根据src
和invert
计算出要移动的方向
let tracker = 0;
//extract logic for the movement offset based on direction
function getDirectionOffset(src) {
return src === 'left' ? 1 : -1;
}
//have a setter for the invert property
function setInverse(isInverse) {
movementModifier = isInverse ? -1 : 1
}
//declare the variable dependent on the inverse property
let movementModifier;
//initialise movementModifier variable
setInverse(false);
function handleDirection(src) {
const offset = getDirectionOffset(src) * movementModifier;
tracker += offset;
}
// usage
setInverse(true);
handleDirection("left");
handleDirection("left");
handleDirection("right");
console.log(tracker);
话虽如此,这一切都表明您不应该使用某个函数,或者应该以不同的方式使用它。您可以在一个类中收集所有这些功能,也可以将所有信息传递给功能,因此您没有全局变量。这是该概念的面向对象的示例实现:
class TrackerMover {
constructor(inverse) {
this.tracker = 0;
this.movementModifier = inverse ? 1 : -1
}
handleDirection(src) {
const offset = this.getDirectionOffset(src) * this.movementModifier;
this.tracker += offset;
}
getDirectionOffset(src) {
return src === 'left' ? -1 : 1;
}
getPosition() {
return this.tracker;
}
}
//usage
const mover = new TrackerMover(true);
mover.handleDirection("left");
mover.handleDirection("left");
mover.handleDirection("right");
console.log(mover.getPosition())
顺便说一句,另一种选择是不每次都计算运动。您实际上知道每次发生的情况-实际上,您有一个真值表,其中的输入分别为src === left
和inverse
,而输出则是您修改跟踪的方式。
+--------+------------+--------+
| isLeft | isInverted | Offset |
+--------+------------+--------+
| true | true | -1 |
| true | false | 1 |
| false | true | 1 |
| false | false | -1 |
+--------+------------+--------+
因此,您只需将桌子放进去。
let tracker = 0;
let invert = false;
const movementLookupTable = {
"true": { },
"false": { },
}
//it can be initialised as part of the above expression but this is more readable
movementLookupTable[true ][true ] = -1;
movementLookupTable[true ][false] = 1;
movementLookupTable[false][true ] = 1;
movementLookupTable[false][false] = -1;
function handleDirection(src) {
const offset = movementLookupTable[src === "left"][invert];
tracker += offset;
}
// usage
invert = true;
handleDirection("left");
handleDirection("left");
handleDirection("right");
console.log(tracker);
在这种情况下,这可能是一个矫kill过正的方法,但是如果有更多的标志(包括更多的 values 用于标志)和/或最终状态,则此方法可能会有用。例如,也许您想引入四个方向,但是如果tracker
是up
或down
,则不必修改。
+-----------+------------+--------+
| direction | isInverted | Offset |
+-----------+------------+--------+
| left | true | -1 |
| left | false | 1 |
| right | true | 1 |
| right | false | -1 |
| up | false | 0 |
| up | true | 0 |
| down | false | 0 |
| down | true | 0 |
+-----------+------------+--------+
如您所见,现在不仅是布尔值,您还可以处理任何值。然后使用表格将invert
更改为windDirection
,因此,如果移动为left
,而windDirection
为right
,则结果为就像现在一样,但是您可能会以left
的方向行进并left
前进,因此您要进一步移动 。或者,您可以移动up
并且风向为left
,这样tracker
(此时为X坐标)将被实际修改。
+-----------+---------------+---------+
| direction | windDirection | OffsetX |
+-----------+---------------+---------+
| left | right | -1 |
| left | up | 1 |
| left | down | 1 |
| left | left | 2 |
| right | up | -1 |
| right | down | -1 |
| right | right | -2 |
| right | left | 1 |
| up | up | 0 |
| up | down | 0 |
| up | left | 1 |
| up | right | -1 |
| down | up | 0 |
| down | down | 0 |
| down | left | 1 |
| down | right | -1 |
+-----------+---------------+---------+
考虑到四个方向和四个风向,将来的逻辑读取和维护都非常麻烦,而如果您只有查找表,这很容易,并且可以轻松扩展以甚至处理对角线(假设它们通过0.5
而不是1
来更改值),只要您从表中获取值,您的算法就不会真正在意。
答案 5 :(得分:3)
这只有一个条件,我发现它的读法比其他答案更直观:
function handleDirection(src) {
if (
((src === 'left') && !inverse) ||
((src === 'right') && inverse)
) {
tracker++;
}
else {
tracker--;
}
}
答案 6 :(得分:3)
如果src == left
或inverse
中的一个为真但不为另一个,则要增加跟踪器,否则要减小跟踪器,这就是“ XOR” ^
运算符的作用:
function handleDirection(src) {
if (src === 'left' ^ inverse) {
tracker++;
} else {
tracker--;
}
}
您可以通过使用三元表达式进一步降低该值:
function handleDirection(src) {
tracker += src === 'left' ^ inverse ? 1 : -1;
}
或者,如果您想避免使用隐式强制转换和“聪明”算术的任何条件:
function handleDirection(src) {
tracker += 1 - 2 * (src === 'right' ^ inverse); // either 1-0=1 or 1-2=-1
}
答案 7 :(得分:3)
您根本不需要任何if
句子。可以执行相同的操作
根据 src 和 inverse 计算正或负增量
只需三元运算符的帮助。
function handleDirection(src) {
tracker += (src == "left" ? 1 : -1) * (inverse ? -1 : 1);
};
顺便说一句。为了提高效率,我建议直接使用数字 递增/递减而不是需要额外处理的字符串 解码。您可以使用常量来实现相同的可读性:
还可以将inverse 优化为在1(非 倒置)和-1(倒置)。
const left = 1;
const right = -1;
var direction = 1;
function handleDirection(src) {
tracker += src * direction;
}
function reverse() { // (Example)
direction = direction * -1;
}
...即使“ right”和“ left”关键字来自某种文本用户 输入,您只需从词典中翻译它们即可:
const steps = {
left = 1;
right = -1;
};
function handleDirection(src) {
tracker += steps[src] * direction;
}
答案 8 :(得分:2)
您可以使用短路语法或三元运算符
// by using short circuiting
function handleDirection(src) {
if (src == 'left') tracker = inverse && tracker-1 || tracker +1
else tracker = inverse && tracker+1 || tracker -1
}
// by using ternary operator
function handleDirection(src) {
if (src == 'left') tracker = inverse ? tracker-1 : tracker +1
else tracker = inverse ? tracker+1 : tracker -1
}
答案 9 :(得分:2)
我不喜欢别的,如果可能的话,尽量避免嵌套。我认为这更自然地传达了inverse
的思想:
function handleDirection(src)
{
let change = 1;
if ('right' == src)
change = -1;
if (inverse)
change = -change;
tracker += change;
}
答案 10 :(得分:0)
我知道这不是直接用“简化”来直接解决问题,但我想为您提供解决几个代码质量问题,同时也使代码更具可读性的答案。
关于副作用
首先,此给定函数会更改外部值。这引入了side effects的问题:
要测试这种功能也要困难得多,因为您必须先“创建状态环境”才能运行测试。
第一个简单的调整就是通过参数接受所有外部值,然后只返回分配给任何内容的1
或-1
值(在您的情况下为tracker
)
带字符串的异或条件
第二,在字符串值上使用if/else
时使用互斥或会导致未定义状态,其中src
可能不是'right'
的东西,但函数的行为就像是{ {1}}。相反,它应该引发异常。在这里使用开关是一个很好的帮助。
将这些点应用于功能
如果考虑到以上几点,总体功能将如下所示:
'right'
您可以轻松测试此功能:
function handleDirection (src, inverse) {
switch (src) {
case 'left':
return inverse ? -1 : 1
case 'right':
return inverse ? 1 : -1
default:
throw new Error(`Unknown src: ${src}`)
}
}
现在,该功能显然已经与handleDirection('left' , true) // -1
handleDirection('left' , false) // 1
handleDirection('right', true) // 1
handleDirection('right', false) // -1
handleDirection('middle',true) // Error: Unknown src: middle
分离了(考虑到重构时的宝贵时间),而且完全清楚该功能的作用。
注意
总结一下,我想强调一点,并不是总是写最简单的代码且行数最少,而是易于阅读/理解的代码。它不像提供的许多解决方案那么短,但是每个人都应该立即了解它的作用。
答案 11 :(得分:-1)
现在您正在比较字符串,我不建议这样做。例如,如果您使用“左”而不是“左”,它将使第一个if语句失败。布尔可能在这里有用,因为您可以保证它只有两个状态。
其中的if语句可以通过conditional operators进行压缩。
也许您正在寻找这样的东西
function handleDirection(src) {
if (src) {
inverse ? tracker-- : tracker++;
} else {
inverse ? tracker++ : tracker--;
}
}
答案 12 :(得分:-3)
您可以使用js中的二维数组类型数据结构,并将所需结果存储在sec和inverse索引处。或JSON。