2010-02-25 64 views
40

我試圖實現以下面的方式在JavaScript XOR:反正有沒有落實在JavaScript XOR

// XOR validation 
    if ((isEmptyString(firstStr) && !isEmptyString(secondStr)) || 
    (!isEmptyString(firstStr) && isEmptyString(secondStr)) 
    { 
    alert(SOME_VALIDATION_MSG); 
    return; 
    } 

有沒有更好的方式JavaScript來做到這一點?

謝謝。

+1

我明白這是一個非常好的問題,但我強烈反對,第一個答案是最好的。有更簡單的解決方案,如果你向下滾動... – Nico

回答

34

我假裝你正在尋找一個邏輯XOR,如JavaScript已經具備了按位一個(^):)

我通常使用一個簡單的三元操作符(罕見的時期之一我使用一個):

if ((isEmptyString(firstStr) ? !isEmptyString(secondStr) 
          : isEmptyString(secondStr))) { 
alert(SOME_VALIDATION_MSG); 
    return; 
} 

編輯:

在@Jeff肉丸楊解工作

if ((!isEmptyString(firstStr)^!isEmptyString(secondStr))) { 
    alert(SOME_VALIDATION_MSG); 
    return; 
} 

你否定了這些值以便在布爾變換它們,然後應用按位異或運算符。也許它不是那麼維護作爲第一個解決方案(也許我太習慣於第一個)

+0

謝謝,我會用這個建議。 – amoran

+0

我沒有理解OP的邏輯中的否定 - 好的! –

+1

只是另一個想法:我喜歡使用按位XOR,因爲我認爲三元運算符很難讓其他人閱讀/理解爲異或。 –

5

結帳this對javascript中異或的不同實現的說明。

只是總結他們幾個就在這裏:

if((isEmptyString(firstStr) || isEmptyString(secondStr)) && !(isEmptyString(firstStr) && isEmptyString(secondStr))) { 
    alert(SOME_VALIDATION_MSG); 
    return; 
} 

OR

if(isEmptyString(firstStr)? !isEmptyString(secondStr): isEmptyString(secondStr)) { 
    alert(SOME_VALIDATION_MSG); 
    return; 
} 

OR

if((isEmptyString(firstStr) ? 1 : 0)^(isEmptyString(secondStr) ? 1 : 0)) { 
    alert(SOME_VALIDATION_MSG); 
    return; 
} 

OR

if(!isEmptyString(firstStr)!= !isEmptyString(secondStr)) { 
    alert(SOME_VALIDATION_MSG); 
    return; 
} 
+0

大聲笑。 4秒的差異:) –

+0

您可以在這裏提供答案,而不是推動用戶離開該網站以獲得他們想要的東西嗎? – Sampson

+0

@Jonathan Sampson - 如果你認爲這會有所幫助,我可以。但究竟是什麼原因將代碼複製到帖子中?該資源已存在 – froadie

5

this引用文章:

不幸的是,JavaScript沒有邏輯異或操作符。

可以「模擬」的XOR運算符的行爲的東西,如:

if(!foo != !bar) { 
    ... 
} 

鏈接的文章討論了幾種替代方法。

+3

您能否在這裏提供答案,而不是推動用戶離開網站以獲得他們想要的東西? – Sampson

+3

複製並粘貼?不可以。爲什麼你不在這裏解釋相同的(或類似的)解決方案,以解決那些遇到這個問題的人。如果你的鏈接明天就中斷了,你的回答將毫無用處。 – Sampson

+1

好文章。最好的答案是在頁面的底部。爲什麼不只是簡單地解釋一下呢? – simon

10

你正在做的布爾值的XOR這是很容易模型轉換爲按位異或(其中JavaScript有):

var a = isEmptyString(firstStr) ? 1 : 0; 
var b = isEmptyString(secondStr) ? 1 : 0; 

if(a^b) { ... } 

http://www.howtocreate.co.uk/xor.html

+2

+1 ...這是我總是被教導做XOR的。 – Robusto

+3

思考你的答案...爲什麼不呢!isEmptyString(firstStr)^!isEmptyString(secondStr) – Eineki

1

JavaScript沒有邏輯XOR運算符,讓你構造似乎是合理的。如果它是數字,那麼你可以使用^,即按位異或運算符。

歡呼

+0

布爾值強制爲1和0,所以你可以在布爾值中使用XOR運算符。 –

8

你可以使用按位異或運算符(^)直接:

if (isEmptyString(firstStr)^isEmptyString(secondStr)) { 
    // ... 
} 

它將爲工作你的例子,因爲布爾型truefalse值被轉換爲10,因爲按位運算符使用32位整數。

該表達式還將返回01,並且該值將被if語句強制回布爾值。

你應該知道使用上述方法時發生的類型強制,如果你正在尋找好的性能,我不會推薦你使用按位運算符,你也可以做一個簡單的函數來做到這一點僅使用布爾邏輯運算符:

function xor(x, y) { 
    return (x || y) && !(x && y); 
} 


if (xor(isEmptyString(firstStr), isEmptyString(secondStr))) { 
    // ... 
} 
2

XOR只是表示「這兩個布爾值不同嗎?」。因此:

if (!!isEmptyString(firstStr) != !!isEmptyString(secondStr)) { 
    // ... 
} 

!! s爲只是爲了保證!=操作比較兩個真正的布爾值,因爲可以想象isEmptyString()回報別的東西(如null虛假,或字符串本身真正的)。

55

正如其他人所指出的那樣,邏輯XOR相同不等於爲布爾值,那麼你可以這樣做:


    // XOR validation 
    if(isEmptyString(firstStr) != isEmptyString(secondStr)) 
    { 
     alert(SOME_VALIDATION_MSG); 
     return; 
    } 
+0

令人驚歎!其實,這很簡單!爲什麼我在此之前沒有人聽過? –

+2

這應該是公認的答案。 *因此*對讀者來說要比用否定和按位異或來更清楚。 – jpatokal

1

這裏是一個可以從兩個容納不少爭議

function XOR() { 
    for (var i = 1; i < arguments.length; i++) 
     if (arguments[0] != arguments[i]) 
      return false; 
    return true; 
} 
的XOR使用的

實施例:

if (XOR(isEmptyString(firstStr), isEmptyString(secondStr))) { 
    alert(SOME_VALIDATION_MSG); 
    return; 
} 
+1

如果參數個數爲奇數,則應用於許多參數的XOR定義爲true,否則爲false。你不能早日退出。 – George

0

這裏是XOR函數,需要一個可變數量的參數(含兩個)。這些論據只需要是真實的或虛假的,而不是truefalse

function xor() { 
    for (var i=arguments.length-1, trueCount=0; i>=0; --i) 
     if (arguments[i]) 
      ++trueCount; 
    return trueCount & 1; 
} 

在我2007 MacBook上的Chrome上,它運行時間爲14 ns,有三個參數。奇怪的是,這個版本略有不同需要對三個參數2935 NS:

function xorSlow() { 
    for (var i=arguments.length-1, result=false; i>=0; --i) 
     if (arguments[i]) 
      result ^= true; 
    return result; 
} 
0

試試這個: function xor(x,y) var result = x || y if (x === y) { result = false } return result }

7

容易些的方法:

if ((x+y) % 2) { 
    //statement 
} 

假設,當然,這兩個變量是真正的布爾值,即10

  • 如果x === y你會得到一個偶數,所以異或將是0
  • 如果x !== y,那麼你會得到一個奇數,所以XOR將1 :)

第二個選擇,如果您發現x != y評估爲XOR,那麼所有你必須做是

if (x != y) { 
    //statement 
} 

這將只是再次評估爲異或。 (我更喜歡這個)

當然,一個不錯的想法是將其實現爲一個函數,但它只是您的選擇。

希望這兩種方法有助於某人!我將這個答案標記爲社區維基,因此可以改進。

+0

你知道如果x和y都是假的,那麼它應該評估爲錯誤的權利? x = 0和y = 0應評估爲false,因此您的兩個示例都不是XOR的實現。 – njfife

+0

第一個我不明白爲什麼它是錯誤的:假&假評估爲假,並且真&假也評估爲假,因爲它們都增加到2的倍數......第二個,'x!=當一個變量爲真而另一個不是真時,y'只能計算爲真。即使'0!= FALSE'評價爲'FALSE',所以我沒有看到你的觀點,對不起... – Nico

+1

我真的不知道我爲什麼這麼想,對不起,你是對的。這些都是簡潔和乾淨的解決方案。 – njfife

1

我希望這將是最短和最乾淨的一個

function xor(x,y){return true==(x!==y);} 

這適用於任何類型的

+0

是不是跟'... return(x!== y)一樣? ...'? – Nico

2

假設你正在尋找布爾XOR工作,這裏是一個簡單的實現。

function xor(expr1, expr2){ 
    return ((expr1 || expr2) && !(expr1 && expr2)); 
} 

以上來自「獨佔析取」({one,but not both})的定義。

0

你可以這樣做:

Math.abs(isEmptyString(firstStr) - isEmptyString(secondStr)) 

的,其結果是XOR運算的結果。

2

由於布爾值truefalse使用它們位運算符時分別轉換爲10,按位異或^可以做雙責爲邏輯異或,以及一個bitwiseone,只要你的價值觀是布爾值(Javascript的「truthy」值不會工作)。這與操作員的否定!很容易達成。

a XOR b是logially相當於表達式如下(短)名單:

!a^!b; 
!a != !b; 

有很多其他形式的可能 - 如!a ? !!b : !b - 但這兩種模式都只有評估ab優勢每次一次(並且如果a爲假並因此不評估爲b,則也不會「短路」),而使用三元運算符?:,OR ||或AND &&的形式將會雙重評估或短路。

這兩個語句中的否定!運算符很重要,因爲幾個原因:它將所有「真值」轉換爲布爾值(「」 - > false,12 - > true等等),以便位運算符具有可以使用的值,所以不等式!=運算符只會比較每個表達式的真值(如果ab是不等於非空字符串等,則a != b將無法​​正常工作)等等每個評估都會返回一個布爾值結果而不是第一個「真值」值。

您可以通過添加雙重否定(或例外,!!a^!!b,仍等同於XOR)來繼續擴展這些表單,但在否定部分表達式時要小心。這些形式可以乍一看似乎是「工作」,如果你在arithmatic分佈來看(其中2(a + b) == 2a + 2b等)的思想,但實際上從XOR產生不同的真值表(these produce similar results to logical NXOR):

!(a^b) 
!(!!a^!!b) 
!!a == !!b 

的XOR的一般形式,那麼,可能是功能(truth table fiddle):然後

function xor(a, b) { return !a^!b; } 

和具體的例子是:

if (xor(isEmptyString(firstStr), isEmptyString(secondStr))) { ... } 

或者如果isEmptyString只返回布爾值,你不想要一個普通xor功能,簡單地說:

if (isEmptyString(firstStr)^isEmptyString(secondStr)) { ... } 
0

@george,我喜歡你的遊刃有餘採取超過2個操作數的功能。我有一個輕微的改善,使其返回更快:

function xor() { 
    for (var i=arguments.length-1, trueCount=0; i>=0; --i) 
     if (arguments[i]) { 
      if (trueCount) 
       return false 
      ++trueCount; 
     } 
    return trueCount & 1; 
}