Hoe krijg je de logische xor van twee variabelen in Python?

Hoe krijg je de logische xor van twee variabelen in Python?

Ik heb bijvoorbeeld twee variabelen waarvan ik verwacht dat het strings zijn. Ik wil testen of slechts één van hen een True-waarde bevat (is niet Geen of de lege tekenreeks):

str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")
if logical_xor(str1, str2):
    print "ok"
else:
    print "bad"

De operator ^ lijkt bitsgewijze te zijn en niet voor alle objecten gedefinieerd:

>>> 1 ^ 1
0
>>> 2 ^ 1
3
>>> "abc" ^ ""
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for ^: 'str' and 'str'

Antwoord 1, autoriteit 100%

Als je de invoer al normaliseert naar booleans, dan is != xor.

bool(a) != bool(b)

Antwoord 2, autoriteit 39%

Je kunt altijd de definitie van xor gebruiken om het uit andere logische bewerkingen te berekenen:

(a and not b) or (not a and b)

Maar dit is mij iets te uitgebreid en op het eerste gezicht niet erg duidelijk. Een andere manier om dit te doen is:

bool(a) ^ bool(b)

De xor-operator op twee booleans is logische xor (in tegenstelling tot ints, waar het bitsgewijs is). Dat is logisch, aangezien bool slechts een subklasse is van int, maar is geïmplementeerd om alleen de waarden 0 en 1 te hebben. En logische xor is gelijk aan bitsgewijze xor wanneer het domein beperkt is tot 0 en 1.

Dus de functie logical_xor zou als volgt worden geïmplementeerd:

def logical_xor(str1, str2):
    return bool(str1) ^ bool(str2)

Met dank aan Nick Coghlan op de Python-3000-mailinglijst.


Antwoord 3, autoriteit 14%

Bitwise exclusief-of is al ingebouwd in Python, in de operator module (die identiek is aan de ^ operator):

from operator import xor
xor(bool(a), bool(b))  # Note: converting to bools is essential

Antwoord 4, autoriteit 3%

Als Zach uitgelegd, je kunt het volgende gebruiken:

xor = bool(a) ^ bool(b)

Persoonlijk ben ik voorstander van een iets ander dialect:

xor = bool(a) + bool(b) == 1

Dit dialect is geïnspireerd op een logische diagramtaal die ik op school heb geleerd, waarbij “OR” werd aangegeven met een vak met ?1 (groter dan of gelijk aan 1) en “XOR” werd aangegeven met een vak met =1.

Dit heeft het voordeel dat het exclusief of op meerdere operanden correct wordt geïmplementeerd.

  • “1 = a ^ b ^ c…” betekent dat het aantal echte operanden oneven is. Deze operator is “pariteit”.
  • “1 = a + b + c…” betekent dat precies één operand waar is. Dit is “exclusief of”, wat betekent “één met uitsluiting van de anderen”.

Antwoord 5, autoriteit 2%

  • Python-logische or: A or B: geeft a terug als bool(A) True, anders retourneert b
  • Python-logische and: A and B: geeft a terug als bool(A) False, anders retourneert b

Om de meeste van die manier van denken te behouden, zou mijn logische xor-definitie zijn:

def logical_xor(a, b):
    if bool(a) == bool(b):
        return False
    else:
        return a or b

Op die manier kan het a, b of False retourneren:

>>> logical_xor('this', 'that')
False
>>> logical_xor('', '')
False
>>> logical_xor('this', '')
'this'
>>> logical_xor('', 'that')
'that'

Antwoord 6, autoriteit 2%

Ik heb verschillende benaderingen getest en not a != (not b) bleek de snelste te zijn.

Hier zijn enkele tests

%timeit not a != (not b)
10000000 loops, best of 3: 78.5 ns per loop
%timeit bool(a) != bool(b)
1000000 loops, best of 3: 343 ns per loop
%timeit not a ^ (not b)
10000000 loops, best of 3: 131 ns per loop

Bewerken:
In voorbeelden 1 en 3 hierboven ontbreken haakjes, dus het resultaat is onjuist. Nieuwe resultaten + truth() werken zoals ShadowRanger suggereerde.

%timeit  (not a) ^  (not b)   # 47 ns
%timeit  (not a) != (not b)   # 44.7 ns
%timeit truth(a) != truth(b)  # 116 ns
%timeit  bool(a) != bool(b)   # 190 ns

Antwoord 7

Python heeft een bitsgewijze exclusieve OR-operator, het is ^:

>>> True ^ False
True
>>> True ^ True
False
>>> False ^ True
True
>>> False ^ False
False

Je kunt het gebruiken door de invoer naar booleans te converteren voordat je xor toepast (^):

bool(a) ^ bool(b)

(Bewerkt – bedankt Arel)


Antwoord 8

Eenvoudig, gemakkelijk te begrijpen:

sum(bool(a), bool(b)) == 1

Als u op zoek bent naar een exclusieve keuze, d.w.z. om 1 keuze uit n te selecteren, kan deze worden uitgebreid tot meerdere argumenten:

sum(bool(x) for x in y) == 1

Antwoord 9

Waardevolle discussie:

Een ander idee… Probeer gewoon de (misschien) pythonische uitdrukking “is niet” om het gedrag van logische “xor” te krijgen

De waarheidstabel zou zijn:

>>> True is not True
False
>>> True is not False
True
>>> False is not True
True
>>> False is not False
False
>>>

En voor uw voorbeeldreeks:

>>> "abc" is not  ""
True
>>> 'abc' is not 'abc' 
False
>>> 'abc' is not '' 
True
>>> '' is not 'abc' 
True
>>> '' is not '' 
False
>>> 

Echter; zoals ze hierboven aangaven, hangt het af van het daadwerkelijke gedrag dat je wilt uittrekken over een paar snaren, omdat snaren geen boleans zijn… en” en “of”
http://www.diveintopython.net/power_of_introspection/and_or.html

Sorry dat ik Engels schrijf, het is niet mijn aangeboren taal.

Met vriendelijke groet.


Antwoord 10

Omdat ik de eenvoudige variant van xor niet zie met variabele argumenten en alleen bewerking op Waarheidswaarden True of False, gooi ik het hier voor iedereen om te gebruiken.
Het is zoals anderen al hebben opgemerkt, behoorlijk (om niet te zeggen heel) rechttoe rechtaan.

def xor(*vars):
    result = False
    for v in vars:
        result = result ^ bool(v)
    return result

En het gebruik is ook eenvoudig:

if xor(False, False, True, False):
    print "Hello World!"

Aangezien dit de gegeneraliseerde n-ary logische XOR is, zal de waarheidswaarde True zijn wanneer het aantal True-operanden oneven is (en niet alleen wanneer er precies één True is, dit is slechts één geval waarin n-ary XOR is waar).

Dus als je op zoek bent naar een n-ary predikaat dat alleen waar is als precies één van zijn operanden is, wil je misschien het volgende gebruiken:

def isOne(*vars):
    result = False
    for v in vars:
        if result and v:
            return False
        else:
            result = result or v
    return result

Antwoord 11

Ik weet dat dit laat is, maar ik had een idee en het is misschien de moeite waard, alleen voor documentatie. Misschien zou dit werken:np.abs(x-y) Het idee is dat

  1. als x=True=1 en y=False=0, dan is het resultaat |1-0|=1=True
  2. als x=False=0 en y=False=0, dan is het resultaat |0-0|=0=False
  3. als x=True=1 en y=True=1 dan is het resultaat |1-1|=0=False
  4. als x=False=0 en y=True=1 dan is het resultaat |0-1|=1=True

Antwoord 12

Exclusief Of wordt als volgt gedefinieerd

def xor( a, b ):
    return (a or b) and not (a and b)

Antwoord 13

Soms merk ik dat ik met 1 en 0 werk in plaats van booleaanse True en False-waarden. In dit geval kan xor worden gedefinieerd als

z = (x + y) % 2

die de volgende waarheidstabel heeft:

     x
   |0|1|
  -+-+-+
  0|0|1|
y -+-+-+
  1|1|0|
  -+-+-+

Antwoord 14

Om de logische xor van twee of meer variabelen in Python te krijgen:

  1. Invoer omzetten naar booleans
  2. Gebruik de bitsgewijze xor-operator (^ of operator.xor)

Bijvoorbeeld

bool(a) ^ bool(b)

Als je de invoer naar booleans converteert, wordt bitwise xor logisch xor.

Merk op dat het geaccepteerde antwoord fout is: != is niet hetzelfde als xor in Python vanwege de subtiliteit van operator chaining.

Bijvoorbeeld, de xor van de drie onderstaande waarden is fout bij gebruik van !=:

True ^  False ^  False  # True, as expected of XOR
True != False != False  # False! Equivalent to `(True != False) and (False != False)`

(P.S. Ik heb geprobeerd het geaccepteerde antwoord te bewerken om deze waarschuwing op te nemen, maar mijn wijziging is afgewezen.)


Antwoord 15

Wat dacht je hiervan?

(not b and a) or (not a and b)

geeft a als b onwaar is
geeft b als a onwaar is
geeft False anders

Of met de Python 2.5+ ternaire expressie:

(False if a else b) if b else a

Antwoord 16

Sommige van de hier voorgestelde implementaties leiden in sommige gevallen tot herhaalde evaluatie van de operanden, wat kan leiden tot onbedoelde bijwerkingen en moet daarom worden vermeden.

Dat gezegd hebbende, een xor-implementatie die True of False retourneert, is vrij eenvoudig; een die, indien mogelijk, een van de operanden retourneert, is veel lastiger, omdat er geen consensus bestaat over welke operand de gekozen moet zijn, vooral wanneer er meer dan twee operanden zijn. Moet bijvoorbeeld xor(None, -1, [], True) None, [] of False? Ik wed dat elk antwoord voor sommige mensen het meest intuïtieve lijkt.

Voor het True- of False-resultaat zijn er maar liefst vijf mogelijke keuzes: return first operand (als het overeenkomt met het eindresultaat in waarde, else boolean), return first match (als er tenminste één bestaat, anders boolean), retourneert de laatste operand (if … else …), retourneert de laatste match (if … else …), of retourneert altijd boolean. In totaal is dat 5 ** 2 = 25 smaken van xor.

def xor(*operands, falsechoice = -2, truechoice = -2):
  """A single-evaluation, multi-operand, full-choice xor implementation
  falsechoice, truechoice: 0 = always bool, +/-1 = first/last operand, +/-2 = first/last match"""
  if not operands:
    raise TypeError('at least one operand expected')
  choices = [falsechoice, truechoice]
  matches = {}
  result = False
  first = True
  value = choice = None
  # avoid using index or slice since operands may be an infinite iterator
  for operand in operands:
    # evaluate each operand once only so as to avoid unintended side effects
    value = bool(operand)
    # the actual xor operation
    result ^= value
    # choice for the current operand, which may or may not match end result
    choice = choices[value]
    # if choice is last match;
    # or last operand and the current operand, in case it is last, matches result;
    # or first operand and the current operand is indeed first;
    # or first match and there hasn't been a match so far
    if choice < -1 or (choice == -1 and value == result) or (choice == 1 and first) or (choice > 1 and value not in matches):
      # store the current operand
      matches[value] = operand
    # next operand will no longer be first
    first = False
  # if choice for result is last operand, but they mismatch
  if (choices[result] == -1) and (result != value):
    return result
  else:
    # return the stored matching operand, if existing, else result as bool
    return matches.get(result, result)
testcases = [
  (-1, None, True, {None: None}, [], 'a'),
  (None, -1, {None: None}, 'a', []),
  (None, -1, True, {None: None}, 'a', []),
  (-1, None, {None: None}, [], 'a')]
choices = {-2: 'last match', -1: 'last operand', 0: 'always bool', 1: 'first operand', 2: 'first match'}
for c in testcases:
  print(c)
  for f in sorted(choices.keys()):
    for t in sorted(choices.keys()):
      x = xor(*c, falsechoice = f, truechoice = t)
      print('f: %d (%s)\tt: %d (%s)\tx: %s' % (f, choices[f], t, choices[t], x))
  print()

Antwoord 17

Xor is ^ in Python. Het geeft terug:

  • Een bitsgewijze xor voor ints
  • Logische xor voor bools
  • Een exclusieve combinatie voor sets
  • Door de gebruiker gedefinieerde resultaten voor klassen die __xor__ implementeren.
  • TypeError voor ongedefinieerde typen, zoals strings of woordenboeken.

Als u van plan bent ze toch op strings te gebruiken, maakt het casten ervan in bool uw bewerking ondubbelzinnig (u kunt ook set(str1) ^ set(str2) bedoelen) .


Antwoord 18

Veel mensen, waaronder ikzelf, hebben een xor-functie nodig die zich gedraagt ​​als een xor-circuit met n-invoer, waarbij n variabel is. (Zie https://en.wikipedia.org/wiki/XOR_gate). De volgende eenvoudige functie implementeert dit.

def xor(*args):
   """
   This function accepts an arbitrary number of input arguments, returning True
   if and only if bool() evaluates to True for an odd number of the input arguments.
   """
   return bool(sum(map(bool,args)) % 2)

Voorbeeld I/O volgt:

In [1]: xor(False, True)
Out[1]: True
In [2]: xor(True, True)
Out[2]: False
In [3]: xor(True, True, True)
Out[3]: True

Antwoord 19

Het is gemakkelijk als je weet wat XOR doet:

def logical_xor(a, b):
    return (a and not b) or (not a and b)
test_data = [
  [False, False],
  [False, True],
  [True, False],
  [True, True],
]
for a, b in test_data:
    print '%r xor %s = %r' % (a, b, logical_xor(a, b))

Antwoord 20

Dit krijgt de logische exclusieve XOR voor twee (of meer) variabelen

str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")
any([str1, str2]) and not all([str1, str2])

Het eerste probleem met deze opstelling is dat het hoogstwaarschijnlijk de hele lijst twee keer doorloopt en, op zijn minst, minstens één van de elementen twee keer zal controleren. Het kan dus het begrip van de code vergroten, maar het zorgt niet voor snelheid (wat verwaarloosbaar kan verschillen, afhankelijk van uw gebruikssituatie).

Het tweede probleem met deze opstelling is dat er wordt gecontroleerd op exclusiviteit, ongeacht het aantal variabelen. Dit kan in eerste instantie als een functie worden beschouwd, maar het eerste probleem wordt veel belangrijker naarmate het aantal variabelen toeneemt (als ze dat ooit doen).


Antwoord 21

Dit is hoe ik elke waarheidstabel zou coderen. Voor xor in het bijzonder hebben we:

| a | b  | xor   |             |
|---|----|-------|-------------|
| T | T  | F     |             |
| T | F  | T     | a and not b |
| F | T  | T     | not a and b |
| F | F  | F     |             |

Kijk maar naar de T-waarden in de antwoordkolom en rijg alle echte gevallen samen met logische of. Dus deze waarheidstabel kan worden geproduceerd in geval 2 of 3. Vandaar,

xor = lambda a, b: (a and not b) or (not a and b)

Antwoord 22

XOR is geïmplementeerd in operator.xor.


Antwoord 23

Aangezien A en B bools zijn.

A is not B

Antwoord 24

De manier waarop Python logische bewerkingen afhandelt, kan verwarrend zijn, dus mijn implementatie geeft de gebruiker de optie (standaard) van een eenvoudig waar/onwaar-antwoord. Het werkelijke Python-resultaat kan worden verkregen door de optionele derde arg in te stellen op Geen.

def xor(a, b, true=True, false=False): # set true to None to get actual Python result
    ab1 = a and not b
    ab2 = not a and b
    if bool(ab1) != bool(ab2):
        return (ab1 or ab2) if true is None else true
    else:
        return false

Antwoord 25

We kunnen eenvoudig xor van twee variabelen vinden door:

def xor(a,b):
    return a !=b

Voorbeeld:

xor(True,False) >>> True

LEAVE A REPLY

Please enter your comment!
Please enter your name here

five + nineteen =

Other episodes