将if语句中的逻辑重构为最小值

时间:2015-02-01 09:16:13

标签: javascript math logic computer-science permutation

前段时间我用SVG编写了一个教育JavaScript应用程序(公司的封闭源代码)。在最基本的形式,应用程序由两列(左和右)组成,每列包含各种几何形状(正方形,三角形,圆形等)

一列中的每个几何形状都可以连接(通过绘制线)到相对列中的另一个几何形状。但是,任一列中的形状都可以与其建立一个或多个连接,具体取决于其设置。

因此设置为{multiple: false}的形状只能有一个连接或来自它。连接是源自它还是源自另一种形状并不重要;一个连接只意味着一个连接,无论其来源如何。

通过绘制线来连接形状的代码部分是一个过于复杂的if语句。这是:

if ((!sourceHasLines && !targetHasLines) ||
  (sourceHasLines && sourceCanMultiply && !targetHasLines) ||
  (sourceHasLines && sourceCanMultiply && targetHasLines && targetCanMultiply) ||
  (!sourceHasLines && !sourceCanMultiply && targetHasLines && targetCanMultiply) || 
  (!sourceHasLines && sourceCanMultiply && targetHasLines && targetCanMultiply)) {
    // Create a line only if one of the above comparisons succeeds
    connection = self.connect($source, $target);
}
  • 来源是指一列中的形状,目标指向相对列中的形状。
  • 用户可以通过先单击第一列中的一个形状,然后单击第二列中的另一个形状,从任一列启动连接。
  • 无法连接同一列中的形状。

现在看一下代码,我觉得if语句中的逻辑可能会被压缩,我已经有了一些想法。但是,我觉得这与排列或其他CS相关逻辑(如离散数学)有关。我大多是自学成才的,所以我想看看有人会如何处理这个并重构上述if语句。

请注意,代码效果很好,但我想知道如何改进它。以下是原型的屏幕截图,其中包含顶行/底行而不是左/右列:

Connect top objects with bottom objects

3 个答案:

答案 0 :(得分:1)

怎么样:

if ((!SL || SM) && (!TL || TM)) ...

即:源必须为空或采用多行,目标必须为空或采用多行

答案 1 :(得分:1)

看看这两行

(!sourceHasLines && !sourceCanMultiply && targetHasLines && targetCanMultiply)

(!sourceHasLines && sourceCanMultiply && targetHasLines && targetCanMultiply)

如果其中任何一个为真,我们将画一条线

让我们来看看

a = source has lines
A = source can multiply
b = target has lines
B = target can multiply

以上两行成为

(1) ~a AND ~ A AND b AND B
(2) ~a AND A AND b AND B

我们正在使用(1)AND(2)进行决策,这使得当源没有线时A(源可以相乘)DONT CARE。

因此这两行可以替换为

(!sourceHasLines && targetHasLines && targetCanMultiply)

现在您的代码变为

if ((!sourceHasLines && !targetHasLines)
    || (sourceHasLines && sourceCanMultiply && !targetHasLines) 
    || (sourceHasLines && sourceCanMultiply && targetHasLines && targetCanMultiply) 
    || (!sourceHasLines && targetHasLines && targetCanMultiply)) {    
    connection = self.connect($source, $target);
}

可以进一步简化为

if ((!sourceHasLines || sourceCanMultiply) && (!targetHasLines || targetCanMultiply )) {    
    connection = self.connect($source, $target);
}

答案 2 :(得分:1)

您可以应用代数来减少代码的逻辑:

假设:

A = sourceHasLines;
B = targetHasLines;
C = sourceCanMultiply;
D = targetCanMultiply;

它将翻译成:

if ((!A && !B) ||
  (A && C && !B) ||
  (A && C && B && D) ||
  (!A && !C && B && D) || 
  (!A && C && B && D)) {
    // Create a line only if one of the above comparisons succeeds
    connection = self.connect($source, $target);
}

将使用代数转换:

(!A * !B) + ( A * C * !B ) + ( A * C * B * D) + ( !A * !C * B * D ) + ( !A * C * B * D )

应用一些数学:

!A * ( !B + ( B * D ) ) + A * C * ( !B + ( B * D ) )

( !B + ( B * D ) ) * ( !A + ( A * C ) ) 

(!A + C) * ( !B + D)

因此:

if(!sourceHasLines || sourceCanMultiply) && ( !targetHasLines || targetCanMultiply)) {
    connection = self.connect($source, $target);
}