簡體   English   中英

如何縮短我的條件陳述

[英]How to shorten my conditional statements

我有一個很長的條件語句,如下所示:

if(test.type == 'itema' || test.type == 'itemb' || test.type == 'itemc' || test.type == 'itemd'){
    // do something.
}

我想知道我是否可以將這個表達式/語句重構為更簡潔的形式。

有關如何實現這一點的任何想法?

您可以使用帶有fall thru的switch語句:

switch (test.type) {

  case "itema":
  case "itemb":
  case "itemc":
  case "itemd":
    // do something
}

將您的值放入數組中,並檢查您的項目是否在數組中:

if ([1, 2, 3, 4].includes(test.type)) {
    // Do something
}

如果您支持的瀏覽器沒有Array#includes方法,則可以使用此polyfill


在簡要解釋~波浪號快捷方式:

更新:既然我們現在有了includes方法,那么使用~ hack就沒有意義了。 對於那些有興趣知道它是如何工作和/或在其他代碼中遇到它的人來說,只需保留它。

而不是檢查indexOf的結果是否>= 0 ,有一個很好的小捷徑:

if ( ~[1, 2, 3, 4].indexOf(test.type) ) {
    // Do something
}

這是小提琴: http//jsfiddle.net/HYJvK/

這是如何運作的? 如果在數組中找到一個項, indexOf將返回其索引。 如果找不到該項,則返回-1 沒有得到太多的細節,在~按位NOT運算符 ,它會返回0只為-1

我喜歡使用~快捷方式,因為它比在返回值上進行比較更簡潔。 我希望JavaScript有一個in_array函數直接返回一個布爾值(類似於PHP),但這只是一廂情願的想法( 更新:現在它。它被稱為includes 。見上文)。 請注意,jQuery的inArray雖然共享PHP的方法簽名,但實際上模仿了本機indexOf功能(如果索引是你真正想要的,那么在不同的情況下這很有用)。

重要提示:使用波浪形快捷方式似乎有爭議,因為有些人強烈認為代碼不夠清晰,應該不惜一切代價避免(請參閱本答復的評論)。 如果你分享他們的情緒,你應該堅持使用.indexOf(...) >= 0解決方案。


一點點解釋:

JavaScript中的整數是有符號的,這意味着最左邊的位被保留為符號位; 一個標志,表示該數字是正數還是負數, 1為負數。

以下是32位二進制格式的一些樣本正數:

1 :    00000000000000000000000000000001
2 :    00000000000000000000000000000010
3 :    00000000000000000000000000000011
15:    00000000000000000000000000001111

現在這里是相同的數字,但負面:

-1 :   11111111111111111111111111111111
-2 :   11111111111111111111111111111110
-3 :   11111111111111111111111111111101
-15:   11111111111111111111111111110001

為什么這些奇怪的組合為負數? 簡單。 負數只是正數+ 1的倒數; 將負數添加到正數應始終為0

要理解這一點,讓我們做一些簡單的二進制算術。

以下是我們如何將-1添加到+1

   00000000000000000000000000000001      +1
+  11111111111111111111111111111111      -1
-------------------------------------------
=  00000000000000000000000000000000       0

以下是我們將-15添加到+15

   00000000000000000000000000001111      +15
+  11111111111111111111111111110001      -15
--------------------------------------------
=  00000000000000000000000000000000        0

我們如何得到這些結果? 通過定期添加,我們在學校教授的方式:從最右邊的列開始,然后添加所有行。 如果總和大於最大的單位數(十進制數為9 ,但二進制數為1 ),則將余數轉移到下一列。

現在,正如您將注意到的,當向其正數添加負數時,不是全0的最右側列將始終具有兩個1秒,當它們一起添加時將導致2 兩個是的二進制表示10 ,我們進行了1到下一列,並把一個0的結果中的第一列。 左邊的所有其他列只有一行1 ,所以從前一列結轉的1將再次加起來2 ,然后將繼續...這個過程重復直到我們到達最左邊列,其中1將被帶走,無處可去,所以它會溢出並丟失,我們只剩下0秒。

該系統稱為2的補充 你可以在這里閱讀更多相關信息:

2對有符號整數的補碼表示


既然2的補碼中的速成課程結束了,你會發現-1是唯一一個二進制表示為1的數字。

使用~按位NOT運算符,給定數字中的所有位都被反轉。 從反轉所有位中獲得0的唯一方法是,如果我們從1開始全部開始。

所以,這一切都是說的一口長氣路~n只會返回0 ,如果n-1

使用科學:你應該做idfah所說的和最快的速度,同時保持代碼簡短:

這是比速度更快~方法

var x = test.type;
if (x == 'itema' ||
    x == 'itemb' ||
    x == 'itemc' ||
    x == 'itemd') {
    //do something
}

http://jsperf.com/if-statements-test-techsin 在此輸入圖像描述 (熱門:Chrome,底部設置:Firefox)

結論:

如果可能性很少,並且您知道某些更可能發生, if || ,則會獲得最大性能 switch fall throughif(obj[keyval])

如果可能性很多 ,並且其中任何一個都可能是最常出現的,換句話說,你不知道哪一個最有可能發生,而不是你從對象查找得到最大的性能if(obj[keyval])regex如果這適合。

http://jsperf.com/if-statements-test-techsin/12

如果出現新的東西,我會更新。

如果要與字符串進行比較並且存在模式,請考慮使用正則表達式。

否則,我懷疑試圖縮短它只會混淆你的代碼。 考慮簡單地包裹線條以使其漂亮。

if (test.type == 'itema' ||
    test.type == 'itemb' ||
    test.type == 'itemc' ||
    test.type == 'itemd') {
    do something.
}
var possibilities = {
  "itema": 1,
  "itemb": 1,
  "itemc": 1,
…};
if (test.type in possibilities) { … }

使用對象作為關聯數組是很常見的事情,但由於JavaScript沒有本機集,因此您也可以將對象用作廉價集。

if( /^item[a-d]$/.test(test.type) ) { /* do something */ }

或者如果物品不均勻,那么:

if( /^(itema|itemb|itemc|itemd)$/.test(test.type) ) { /* do something */ }

很好的答案,但你可以通過將其中一個包裝在一個函數中使代碼更具可讀性。

如果聲明很復雜,當您(或其他人)在幾年內閱讀代碼時,您將通過掃描查找該部分以了解發生的情況。 具有此級別業務邏輯的語句將導致您在計算出正在測試的內容時偶然發現幾秒鍾。 像這樣的代碼,將允許您繼續掃描。

if(CheckIfBusinessRuleIsTrue())
{
    //Do Something
}

function CheckIfBusinessRuleIsTrue() 
{
    return (the best solution from previous posts here);
}

明確命名您的函數,以便立即明確您正在測試的內容,並且您的代碼將更容易掃描和理解。

您可以將所有答案放入Javascript集中 ,然后在集合上調用.contains()

您仍然必須聲明所有內容,但內聯呼叫將更短。

就像是:

var itemSet = new Set(["itema","itemb","itemc","itemd"]);
if( itemSet.contains( test.type ){}

我最喜歡的方法之一是使用諸如underscore.js之類的庫...

var isItem = _.some(['itema','itemb','itemc','itemd'], function(item) {
    return test.type === item;
});

if(isItem) {
    // One of them was true
}

http://underscorejs.org/#some

我發現的另一種方式或者另一種方式是......

if ('a' in oc(['a','b','c'])) { //dosomething }

function oc(a)
{
  var o = {};
  for(var i=0;i<a.length;i++)  o[a[i]]='';
  return o;
}

當然,正如您所看到的,這會使事情更進一步,並使它們更容易遵循邏輯。

http://snook.ca/archives/javascript/testing_for_a_v

使用〜&& ||等運算符 ((),())~~只有在以后代碼中斷時才可以。 你不會知道從哪里開始。 所以可讀性很高。

如果你必須你可以縮短它。

('a' in oc(['a','b','c'])) && statement;
('a' in oc(['a','b','c'])) && (statements,statements);
('a' in oc(['a','b','c']))?statement:elseStatement;
('a' in oc(['a','b','c']))?(statements,statements):(elseStatements,elseStatements);

如果你想反過來

('a' in oc(['a','b','c'])) || statement;

只需使用switch語句而不是if語句:

switch (test.type) {

  case "itema":case "itemb":case "itemc":case "itemd":
    // do your process
  case "other cases":...:
    // do other processes
  default:
    // do processes when test.type does not meet your predictions.
}

Switch也比在if比較大量條件更快

對於非常長的字符串列表,這個想法會節省一些字符(不是說我在現實生活中推薦它,但它應該工作)。

選擇一個你知道在test.type中不會出現的字符,將它用作分隔符,將它們全部粘貼到一個長字符串中並搜索:

if ("/itema/itemb/itemc/itemd/".indexOf("/"+test.type+"/")>=0) {
  // doSomething
}

如果你的字符串碰巧被進一步限制,你甚至可以省略分隔符......

if ("itemaitembitemcitemd".indexOf(test.type)>=0) {
  // doSomething
}

...但在這種情況下你必須小心誤報(例如“embite”會匹配該版本)

為了便於閱讀,請為測試創建一個函數(是的,一行函數):

function isTypeDefined(test) {
    return test.type == 'itema' ||
           test.type == 'itemb' ||
           test.type == 'itemc' ||
           test.type == 'itemd';
}

然后叫它:

…
    if (isTypeDefined(test)) {
…
}
...

我認為在編寫這種if條件時有兩個目標。

  1. 簡短
  2. 可讀性

因此有時候#1可能是最快的,但是我會在以后輕松維護#2。 根據情況,我會經常選擇瓦爾特答案的變體。

首先,我將全局可用功能作為現有庫的一部分。

function isDefined(obj){
  return (typeof(obj) != 'undefined');
}

然后,當我真的想要運行類似於你的if條件時,我會創建一個帶有有效值列表的對象:

var validOptions = {
  "itema":1,
  "itemb":1,
  "itemc":1,
  "itemd":1
};
if(isDefined(validOptions[test.type])){
  //do something...
}

它不像switch / case語句那么快,比其他一些例子更冗長,但我經常在代碼中的其他地方重用對象,這可能非常方便。

在上面制作的一個jsperf樣本上捎帶我添加了這個測試和一個比較速度的變化。 http://jsperf.com/if-statements-test-techsin/6我注意到最有趣的事情是Firefox中的某些測試組合比Chrome更快。

這可以通過一個簡單的for循環來解決:

test = {};
test.type = 'itema';

for(var i=['itema','itemb','itemc']; i[0]==test.type && [
    (function() {
        // do something
        console.log('matched!');
    })()
]; i.shift());

我們使用for循環的第一部分來初始化你想要匹配的參數,第二部分用來阻止for循環運行,第三部分用來使循環最終退出。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM