2009-02-23 45 views
1
if (x() > 10) 
{ 
    if (y > 5) 
     action1(p1, p2, p3, p4); 
    else 
     action2(p1, p2); 
} 
else 
{ 
    if (z > 2) 
     action1(p1, p2, p3, p4); 
    else 
     action2(p1, p2); 
}   

我真正的項目在我的,行動1和行動2實際上是2-3行代碼和被調用的這些函數總共需要6-8個參數,因此將它們編寫爲單個函數似乎不正確。你會如何縮短這一點,使action1和action2只在代碼中出現一次?

更新:我忘了提及這一點,現在我看到很多答案都不起作用。 x()是昂貴的操作並且有副作用,所以它不應該被調用兩次。

+0

在第2個動作2額外的逗號是一個錯字? – 2009-02-23 16:39:07

+0

從一開始就檢查代碼以避免混淆會更好,但現在只需添加第一個「int x_result = x();」就可以自動工作「不工作」的答案。然後在表達式中使用x_result。 – 2009-02-23 17:06:45

回答

8
bool condition_satisfied = (x() > 10 ? y > 5 : z > 2); 
if (condition_satisfied) 
    action1(p1, p2, p3, p4); 
else 
    action2(p1, p2); 

或者,或者,羅傑Lipscombe answered

10

你總是可以這樣做:

if ((x > 10) ? (y >5) : (z > 2)) action1 
else action2 

爲了完整起見,任何if p then q else r說法在邏輯上可以表示爲(!p && r) || q。因此,我們可以表達原文的語句:

(!a && !c && action2) || 
(!a && c && action1) || 
(a && !b && action2) || 
(a && b && action1) 

如果您收集動作1到一邊,你會得到:

(a && b && action1) || 
(!a && c && action1) || 

(a && !b && action2) || 
(!a && !c && action2) 

a = x > 10 
b = y > 5 
c = z > 2 
(!a && (!c && action2) || ((!b && action2) || action1)) 

,你可以作爲擴大了真正擴展爲:

(a && b && c && action1) || 
(a && b && !c && action1) || 
(!a && b && c && action1) || 
(!a && !b && c && action1) || 

(a && !b && c && action2) || 
(a && !b && !c && action2) || 
(!a && b && !c && action2) || 
(!a && !b && !c && action2) 

而且從我們可以看到,我們可以把它簡化爲:

(a && b && c && action1) || 
(a && b && !c && action1) || 
(!a && b && c && action1) || 
(!a && !b && c && action1) || 
action2 

由於導致動作2路全是導致動作1的任何路徑的否定,我們可以進一步簡化爲:

(a && b && action1) || 
(!a && c && action1) || 
action2 

哪本身可以簡化爲:

(((a && b &&) || (!a && c)) && action1) || 
action2 

然後可以寫爲:

if ((a && b) || (!a && c)) action1 
else action2 

哪一個變成: if((x> 10 & & y> 5)|| (!(x> 10)& & z> 2))action1 else action2

這是我們無論如何得到的。

+0

這種情況出現很多。有兩點需要注意:1)可讀性勝過輕微的效率提升; 2)熟悉布爾邏輯和您可以執行的優化。 – dwc 2009-02-23 16:42:31

+0

如果x> 10 && z> 2,這將觸發action1,問題中的版本不會。 – 2009-02-23 16:43:44

+0

這不太對。如果x> 10且y <=5, but z> 2,則它將在執行動作2時執行動作1. – gnovice 2009-02-23 16:44:25

5

我喜歡原始的,詳細的版本。但前提是它遵循代碼描述的系統內部邏輯。否則,也許應該是 「對立」:

int xRes = x(); 
if (y > 5) 
{ 
    if (xRes > 10) 
     action1(p1, p2, p3, p4); 
    else 
     action2(p1, p2); 
} 
else if (z > 2) 
{ 
    if (xRes > 10) 
     action1(p1, p2, p3, p4); 
    else 
     action2(p1, p2); 
} 
else 
{ 
    action2(p1, p2); 
} 

無論如何,如果你有興趣在最短的解決方案,這可能是它:

((x>10 && y>5) || (x<=10 && z>2)) ? action1(p1, p2, p3, p4) : action2(p1, p2); 
12
if ((x > 10 && y > 5) || (x <= 10 && z > 2)) 
    action1(p1, p2, p3, p4); 
else 
    action2(p1, p2); 
15
if (should_do_action1(x(), y, z)) 
    action1(p1, p2, p3, p4); 
else 
    action2(p1, p2); 
1

如果你想要做到這一點只有1條語句,我認爲它會是:

if ((x > 10) && (y > 5)) || ((x <= 10) && (z > 2)) 
    action1(p1, p2, p3, p4); 
else 
    action2(p1, p2); 
2
//Yeah, I know this is wrong. Explanation below. 
if ((x() > 10 && y > 5) || (x() <= 10 && z > 2)) 
    action1(p1, p2, p3, p4); 
else 
    action2(p1, p2); 

更改了代碼,因爲我的條件邏輯錯了。

但個人而言,爲了便於閱讀,我更喜歡你的更詳細的版本。

正如評論已經注意到,我似乎很難得到這個完全正確的。我會注意到這是因爲我會這麼做的方式幾乎是這個問題最初的表述。我更喜歡布爾運算符的字符串冗長,因爲在我看來,它使得操作的邏輯更容易可視化。

3

我想不出更清楚或簡單地表達它的方法。它可以縮短,但會讓它更難理解。

1

你知道,在看到這裏的一些迴應後,我不得不說你的原始版本更具可讀性,當然更容易理解。我會做的唯一的變化是對其他線,指出其他情況下是X加少許評論< = 10

我不認爲縮短代碼是真的大問題因爲幾乎任何原因。我知道如果你是一個老派的編碼器,你希望儘可能簡潔,但我們都有100 + Gb驅動器和編譯器,無論如何都會將這些替代品中的任何一個替換爲相同的代碼,爲什麼不選擇可讀性?我的2美分:)

2

因爲x()很貴,所以緩存結果。再結合上動作1的前提條件:

int x = x(); 
if ((x>10 && y>5) || (x<=10 && z>2)) 
{ 
    action1(p1,p2,p3,p4); 
} 
else 
{ 
    action2(p1,p2); 
} 
1
var valX= x(); 
if ((valX > 10 && y>5) || (valX<=10 && z>2)) 
{ 

     action1(p1, p2, p3, p4); 
} 
else 
{ 
     action2(p1, p2); 
}