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
: geefta
terug alsbool(A)
True
, anders retourneertb
- Python-logische
and
:A and B
: geefta
terug alsbool(A)
False
, anders retourneertb
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
- als x=True=1 en y=False=0, dan is het resultaat |1-0|=1=True
- als x=False=0 en y=False=0, dan is het resultaat |0-0|=0=False
- als x=True=1 en y=True=1 dan is het resultaat |1-1|=0=False
- 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:
- Invoer omzetten naar booleans
- Gebruik de bitsgewijze xor-operator (
^
ofoperator.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