Gibt es eine bessere Schreibweise für v = (v == 0? 1: 0); [geschlossen]

465

Ich möchte eine Variable zwischen 0 und 1 umschalten. Wenn es 0 ist, möchte ich sie auf 1 setzen, andernfalls möchte ich sie auf 0 setzen, wenn es 1 ist.

Dies ist eine so grundlegende Operation, dass ich so oft schreibe, dass ich den kürzesten und klarsten Weg untersuchen möchte. Hier ist mein bisher bestes:

v = (v == 0 ? 1 : 0);

Können Sie das verbessern?

Bearbeiten: Die Frage lautet, wie die obige Aussage in den wenigsten Zeichen geschrieben werden soll, während die Klarheit erhalten bleibt - wie ist dies "keine echte Frage"? Dies war nicht als Code-Golf-Übung gedacht, obwohl einige interessante Antworten von Leuten kamen, die es als Golf betrachteten - es ist schön zu sehen, wie Golf konstruktiv und zum Nachdenken anregend eingesetzt wird.

Ollie Glass
quelle
20
Das sieht für mich schon einfach / klar / kurz aus.
Mob
136
v = +!v;
trickery
48
Wenn "besser" auch "schneller" bedeutet: jsperf.com/v-0-1-0 .
Pimvdb
7
@Mobinga: +1. Dies ist so einfach wie es nur sein sollte. Alle anderen Antworten, die ich sehe, sind verwirrend, und einige von ihnen ändern die Logik; Fehler einführen.
Ian Boyd
8
@holodoc Eine bessere Lösung, um Ihre Meinung zu äußern, wäre, eine Antwort zu erstellen, die besagt, dass Sie der Meinung sind, dass das Original der beste Weg ist, und zu erläutern, WARUM Sie der Meinung sind, dass dies der Fall ist. Dies ermöglicht es auch anderen Personen, sich Ihrer Antwort leicht anzuschließen, indem sie sie abstimmen.
Chuck van der Linden

Antworten:

721

Sie können einfach verwenden:

v = 1 - v;

Dies setzt natürlich voraus, dass die Variable richtig initialisiert ist, dh dass sie nur den Wert 0 oder 1 hat.

Eine andere Methode, die kürzer ist, aber einen weniger gebräuchlichen Operator verwendet:

v ^= 1;

Bearbeiten:

Deutlich sein; Ich bin dieser Frage nie als Code-Golf begegnet, nur um einen kurzen Weg zu finden, die Aufgabe zu erledigen, ohne irgendwelche undurchsichtigen Tricks wie Nebenwirkungen von Bedienern anzuwenden.

Guffa
quelle
206
Dies sind wunderschöne Codezeilen wie fein geschnittenes Glas oder seltene blühende Orchideen. Ich finde es toll, wie Sie direkt durch die logische Ebene gelangt sind und sich direkt mit der Mathematik von 1 und 0 befasst haben, mit den bestmöglichen Operationen. Ich werde diese in meinen eigenen Projekten verwenden, aber wenn ich den Code für Mitarbeiter verstehen muss, muss ich leider einen logischeren Ansatz verwenden. Vielen Dank, Ihre Antwort hat meinen Tag gemacht.
Ollie Glass
37
Sie können jederzeit einen Kommentar hinzufügen, der besagt, was der Code bewirkt.
Prusse
25
@ Kevin: Es ist nicht wahr, dass dies die gestellte Frage eindeutig nicht beantwortet. Das q sagte "Ich möchte eine Variable zwischen 0 und 1 umschalten." Eine sehr vernünftige Interpretation ist, dass dies impliziert, dass der Wert der Variablen bereits entweder 0 oder 1 ist. Diese Interpretation / Einschränkung wurde in der Antwort explizit angegeben. Was in aller Welt können Sie beanstanden?
LarsH
50
@ Matthew zu sagen, dass jemand, der nicht v ^= 1klar findet , sollte aufhören zu programmieren, ist ein wenig hart, denke ich. Wie bereits erwähnt, ist es nicht einer der gebräuchlichsten Operatoren und macht nicht das Gleiche wie v = v ^ 1. Auch der Operator meint in verschiedenen Sprachen (VB) etwas völlig anderes. Ja, eine schnelle Suche zeigt Ihnen, dass es sich um einen XOR-Operator handelt, und Sie werden verstehen, was er tut, aber für viele ist dies auf den ersten Blick möglicherweise nicht offensichtlich. Ich glaube nicht, dass Sie Ihren Job kündigen müssen.
JD Isaacks
80
Wenn Sie 15 Zeichen speichern, indem Sie dies schreiben, aber dann 40 Zeichen Kommentare verwenden, um es zu erklären, ist es wirklich eine Verbesserung?
Michael Myers
343

Da 0ist ein falseWert und 1ist ein trueWert.

v = (v ? 0 : 1);

Wenn Sie gerne trueund falseanstelle von Zahlen verwenden

v = !v;

oder wenn es Zahlen sein müssen:

v = +!v; /* Boolean invert v then cast back to a Number */
QUentin
quelle
55
Stellen Sie einfach die Magie +davor !. Ohhh das sieht soooo dreckig aus! aber cool: p
jAndy
1
@ Quentin - dies wird den Code des Mannes brechen, wenn er hat switch(v){ case 0 ...oder wenn (v == 0) oder wenn v === 0. Sie ändern sein Ergebnis zusätzlich zu seinem Ansatz ....
Brian
34
Machen Sie einen Smiley daraus : ({v :+! v}).v.
Pimvdb
17
@ Brian: nicht mit diesem magischen +Zeichen! ¯ \ _ (ツ) _ / ¯
jAndy
11
+1 für v = (v ? 0 : 1)so klar und idiomatisch JS.
Bennett McElwee
200

v = (v + 1) % 2und wenn Sie mehr Werte durchlaufen müssen, ändern Sie einfach 2für (n + 1). Angenommen, Sie müssen nur 0,1,2 durchlaufen v = (v + 1) % 3.

Prusse
quelle
2
Ich liebe den Zyklus! Das ist wirklich klug.
Ollie Glass
16
+1 für das Nachdenken über das Umschalten als Zyklus. Einfach, wenn man bedenkt, wie flexibel es ist.
Guffa
3
+1 für die Bereitstellung einer modularen Lösung, die auch robust ist. In der Praxis möchten Sie wahrscheinlich eine constVariable anstelle der magischen Zahlen 2, 3, ...
oosterwal
2
Kürzere (hackigere) Art: ++v % 3Wenn Sie durch 0, 1, 2
radeln
75

Sie können eine Funktion dafür schreiben und wie folgt verwenden:

v = inv(v)

Daniel
quelle
30
+1 Ich stimme voll und ganz zu, dass dies die sauberste Lösung ist (... aber was dann in der invFunktion steht: P)
Lea Hayes
4
Ich wünschte, ich könnte diese Antwort mehr als nur +1 geben. Wenn allgemeiner Code nicht offensichtlich ist, sollte er in eine Funktion mit einem beschreibenden Namen eingeschlossen werden.
TheShrike
11
@TehShrike halten Sie für inveinen beschreibenden Namen?
Bennett McElwee
3
@ Bennett McElwee: inv = invertieren. Mir kam es immer wie eine gebräuchliche Abkürzung vor.
Daniel
51
Warum es dann abkürzen, es "invertieren" oder "umschalten" nennen und den Code lesbar machen. Es ist nicht so, als würden wir versuchen, dieses Zeug auf eine Lochkarte mit 80 Spalten oder so zu passen.
Chuck van der Linden
50

Wenn Sie sich für keine andere Möglichkeit als 1 interessieren:

v = v ? 0 : 1;

Im obigen Fall wird v 1, wenn v 0, falsch, undefiniert oder null ist. Seien Sie vorsichtig mit diesem Ansatz - v ist 0, auch wenn v "Hallo Welt" ist.

Brian
quelle
2
Das wird den Wert nicht umdrehen. Du meinst v = v ? 0 : 1.
Guffa
3
@ Guffa - +1 für meine Legasthenie ...
Brian
3
Dies ist meine bevorzugte logikbasierte Antwort, die ich mit Kollegen verwenden kann (ich sehe @ Guffas Antwort als zahlenbasiert). Mir gefällt, wie Sie den unnötigen Test (v == 0) und die Klammern herausgenommen und auf die absolute Mindestzeichenzahl reduziert haben. Vielen Dank.
Ollie Glass
1
Ich bin auch ein großer Fan von @ Guffas Antwort - in den Worten von Lynard Skynard, halte es einfach, Mann;)
Brian
2
+1 für das Verständnis von "wahrheitsgemäßen" Werten.
zzzzBov
44

Linien mögen v = 1 - voder v ^= 1oder v= +!vwerden alle die Arbeit erledigen, aber sie bilden das, was ich als Hacks bezeichnen würde. Dies sind keine schönen Codezeilen, sondern billige Tricks, um den beabsichtigten Effekt zu erzielen. 1 - vkommuniziert nicht "den Wert zwischen 0 und 1 umschalten". Dies macht Ihren Code weniger ausdrucksstark und führt einen Ort ein (wenn auch einen kleinen), an dem ein anderer Entwickler Ihren Code analysieren muss.

Eine Funktion wie zu haben, v = toggle(v)vermittelt die Absicht auf den schnellsten Blick.

Strahl
quelle
8
-1, im Ernst, v=1-vkommuniziert der Umschalter nicht?
Blindy
22
1-vkann zwar umschalten kommunizieren, aber das ist das einzige, was es kommuniziert. Beispielsweise kann es auch eine Linie mit Null bei v=1oder eine Spiegeltransformation zentriert bei zentrieren v=0.5. In diesem Sinne ist es relativ vieldeutig. Es ist wahr, dass das Wissen, dass vdies immer nur die beabsichtigte Bedeutung sein 0oder 1einschränken kann, aber andere Entwickler (oder Ihr zukünftiges Selbst) dazu zwingt, diesen Kontext zu verstehen, bevor sie diese einfache Linie verstehen können. Sie können nicht viel klarer sein alsv = toggle(v)
Ray
10
v ^= 1Es ist jedoch völlig klar, wenn Sie logische Operationen verstehen, die Sie als Programmierer besser hätten. Ich denke, das ist der Unterschied zwischen dem und v=1-v; Es ist eine logische Operation und eine arithmetische Operation, und wir versuchen, ein logisches Konzept darzustellen, kein mathematisches.
Matthew Read
6
@Matthew Read: Dies ist eine großartige Aussage, die meine Gedanken gut zusammenfasst: "Wir versuchen, ein logisches Konzept darzustellen, kein mathematisches." Hat v ^= 1aber auch einige Unklarheiten, da es als bitweises xor interpretiert werden kann.
Ray
6
Für Programmierer (und ja, ich meine Geeks wie uns) sind diese ziemlich klar. Sie sind keine Hacks, weil sie aufgrund ihrer Einfachheit elegante Lösungen sind.
gion_13
38

( Ehrlichkeit und mathematische Integrität - angesichts der Anzahl der Stimmen zu dieser "Antwort" - haben mich veranlasst, diese Antwort zu bearbeiten. Ich habe mich so lange wie möglich zurückgehalten, weil sie als kurzer Witz gedacht war und nicht als etwas "Tiefes", das so hineingesteckt wurde Jede Erklärung schien dem Zweck zu widersprechen. Die Kommentare machen jedoch deutlich, dass ich klar sein sollte, um Missverständnisse zu vermeiden. )

Meine ursprüngliche Antwort:

Der Wortlaut dieses Teils der Spezifikation:

Wenn es 0 ist, möchte ich es auf 1 setzen, sonst setze ich es auf 0.

impliziert, dass die genaueste Lösung ist:

v = dirac_delta(0,v)

Erstens das Geständnis: Ich habe meine Delta-Funktionen verwirrt. Das Kronecker-Delta wäre etwas passender gewesen, aber nicht viel, da ich etwas wollte, das domänenunabhängig ist (das Kronecker-Delta wird hauptsächlich nur für ganze Zahlen verwendet). Aber ich hätte wirklich überhaupt keine Delta-Funktionen verwenden sollen, ich hätte sagen sollen:

v = characteristic_function({0},v)

Lassen Sie mich das klarstellen. Denken Sie daran, dass eine Funktion ein Tripel ist (X, Y, f) , wobei X und Y Mengen sind (als Domäne bzw. Codomäne bezeichnet) und f eine Regel ist, die jedem Element von X ein Element von Y zuweist . Wir schreiben oft die dreifache (X, Y, f) als f: X → Y . Bei einer Teilmenge von X , beispielsweise A , gibt es eine charakteristische Funktion, die eine Funktion χ A : X → {0,1} ist.(Es kann auch als Funktion einer größeren Codomäne wie ℕ oder ℝ angesehen werden.) Diese Funktion wird durch die Regel definiert:

χ A (x) = 1 wenn x ∈ A und χ A (x) = 0 wenn x ∉ A .

Wenn Sie Wahrheitstabellen mögen, ist dies die Wahrheitstabelle für die Frage "Ist das Element x von X ein Element der Teilmenge A ?".

Aus dieser Definition geht hervor, dass die charakteristische Funktion hier benötigt wird, wobei X eine große Menge enthält, die 0 und A = {0} enthält . Das hätte ich schreiben sollen.

Und so zu Delta-Funktionen. Dazu müssen wir uns mit Integration auskennen. Entweder du weißt es schon oder du weißt es nicht. Wenn Sie dies nicht tun, kann Ihnen nichts, was ich hier sagen kann, über die Feinheiten der Theorie erzählen, aber ich kann eine Zusammenfassung mit einem Satz geben. Ein Maß für eine Menge X ist im Wesentlichen "das, was benötigt wird, damit Durchschnittswerte funktionieren". Das heißt, wenn wir eine Menge X und ein Maß μ auf dieser Menge haben, dann gibt es eine Klasse von Funktionen X → ℝ , die messbare Funktionen genannt werden, für die der Ausdruck X f dμ Sinn macht und in einem vagen Sinn ist die „durchschnittliche“ von f über X .

Bei einer bestimmten Kennzahl für eine Menge kann eine "Kennzahl" für Teilmengen dieser Gruppe definiert werden. Dies erfolgt durch Zuweisen des Integrals seiner charakteristischen Funktion zu einer Teilmenge (vorausgesetzt, dies ist eine messbare Funktion). Dies kann unendlich oder undefiniert sein (die beiden unterscheiden sich geringfügig).

Es gibt viele Maßnahmen, aber es gibt zwei, die hier wichtig sind. Eines ist das Standardmaß auf der realen Linie, ℝ. Für diese Maßnahme ist f dμ so ziemlich das, was Sie in der Schule lernen (wird in Schulen noch Kalkül unterrichtet?): Fassen Sie kleine Rechtecke zusammen und nehmen Sie immer kleinere Breiten. In diesem Maß ist das Maß eines Intervalls seine Breite. Das Maß eines Punktes ist 0.

Ein weiteres wichtiges Maß, das für jede Menge funktioniert , wird als Punktmaß bezeichnet . Es ist so definiert, dass das Integral einer Funktion die Summe ihrer Werte ist:

X f dμ = ∑ x ∈ X f (x)

Diese Kennzahl weist jeder Singleton-Menge die Kennzahl 1 zu. Dies bedeutet, dass eine Teilmenge genau dann eine endliche Kennzahl hat, wenn sie selbst endlich ist. Und nur sehr wenige Funktionen haben ein endliches Integral. Wenn eine Funktion ein endliches Integral hat, darf sie nur bei einer zählbaren Anzahl von Punkten ungleich Null sein . Die überwiegende Mehrheit der Funktionen, die Sie wahrscheinlich kennen, hat unter dieser Maßnahme kein endliches Integral.

Und nun zu Delta-Funktionen. Nehmen wir eine sehr breite Definition. Wir haben einen Meßraum (X, μ) (so dass ein Satz mit einem Maße darauf) und ein Element a ∈ X . Wir "definieren" die Delta-Funktion (abhängig von a ) als die "Funktion" δ a : X → ℝ mit der Eigenschaft, dass δ a (x) = 0 ist, wenn x ≠ a und X δ a dμ = 1 sind .

Die wichtigste Tatsache, um dies zu erreichen, ist folgende: Die Delta-Funktion muss keine Funktion sein . Es ist nicht richtig definiert: Ich habe nicht gesagt, was δ a (a) ist.

Was Sie an diesem Punkt tun, hängt davon ab, wer Sie sind. Die Welt teilt sich hier in zwei Kategorien. Wenn Sie Mathematiker sind, sagen Sie Folgendes:

Okay, die Delta-Funktion ist möglicherweise nicht definiert. Schauen wir uns seine hypothetische Eigenschaften und sehen , ob wir ein richtiges Zuhause für sie finden kann , wo es ist , definiert. Wir können das und haben am Ende Verteilungen . Dies sind keine (notwendigerweise) Funktionen, sondern Dinge, die sich ein wenig wie Funktionen verhalten, und oft können wir mit ihnen arbeiten, als wären sie Funktionen; Aber es gibt bestimmte Dinge, die sie nicht haben (wie "Werte"), also müssen wir vorsichtig sein.

Wenn Sie kein Mathematiker sind, sagen Sie Folgendes:

Okay, die Delta-Funktion ist möglicherweise nicht richtig definiert. Wer sagt das? Ein Haufen Mathematiker? Ignoriere sie! Was wissen sie?

Nachdem ich jetzt mein Publikum beleidigt habe, werde ich weitermachen.

Das Dirac-Delta wird normalerweise als Delta-Funktion eines Punktes (oft 0) in der realen Linie mit seinem Standardmaß angenommen. Diejenigen, die sich in den Kommentaren darüber beschweren, dass ich meine Deltas nicht kenne, tun dies, weil sie diese Definition verwenden. Ich entschuldige mich bei ihnen: Obwohl ich mich mit der Verteidigung des Mathematikers (wie von Humpty Dumpty populär gemacht : einfach alles neu definieren, damit es richtig ist) daraus herauswinden kann, ist es eine schlechte Form, einen Standardbegriff zu verwenden, um etwas anderes zu bedeuten.

Aber es gibt eine Delta-Funktion, die macht, was ich will, und es ist das, was ich hier brauche. Wenn ich einen nehmen Punktmaß auf einem Satz X dann gibt ist eine echte Funktion δ ein : X → ℝ welche Folgendes erfüllt die Kriterien für eine Delta - Funktion. Dies liegt daran, dass wir nach einer Funktion X → ℝ suchen, die außer bei a Null ist und bei der die Summe aller ihrer Werte 1 ist. Eine solche Funktion ist einfach: Die einzige fehlende Information ist ihr Wert bei a und Um die Summe auf 1 zu bringen, weisen wir ihr einfach den Wert 1 zu. Dies ist nichts anderes als die charakteristische Funktion auf {a} . Dann:

X δ a dμ = ∑ x ∈ X δ a (x) = δ a (a) = 1.

In diesem Fall stimmen für eine Singleton-Menge die charakteristische Funktion und die Delta-Funktion überein.

Zusammenfassend gibt es hier drei Familien von "Funktionen":

  1. Die charakteristischen Funktionen von Singleton-Mengen,
  2. Die Delta-Funktionen,
  3. Das Kronecker-Delta funktioniert.

Die zweite davon ist die allgemeinste, da jede der anderen ein Beispiel dafür ist, wenn das Punktmaß verwendet wird. Aber der erste und dritte haben den Vorteil, dass sie immer echte Funktionen sind. Der dritte ist eigentlich ein Sonderfall des ersten für eine bestimmte Familie von Domänen (Ganzzahlen oder eine Teilmenge davon).

Als ich die Antwort ursprünglich schrieb, dachte ich schließlich nicht richtig (ich würde nicht so weit gehen zu sagen, dass ich verwirrt war , da ich hoffe, ich habe gerade gezeigt, dass ich weiß , wovon ich spreche, wenn Ich denke eigentlich zuerst, ich habe nur nicht viel nachgedacht). Die übliche Bedeutung des Dirac-Deltas ist hier nicht erwünscht, aber einer der Punkte meiner Antwort war, dass die Eingabedomäne nicht definiert wurde, so dass das Kronecker-Delta auch nicht richtig gewesen wäre. Die beste mathematische Antwort (die ich anstrebte) wäre also die charakteristische Funktion gewesen.

Ich hoffe, dass das alles klar ist; und ich hoffe auch, dass ich nie wieder ein mathematisches Stück mit HTML-Entitäten anstelle von TeX-Makros schreiben muss!

Andrew Stacey
quelle
37
+1 - Wenn ich Quentin dafür herabstimmen könnte, dass er die dirac_delta-Funktion nicht kennt, würde ich. Ich würde gerne wissen, auf welches College er gegangen ist, weil ich nicht glaube, dass ich jemanden von dort einstellen würde, wenn er nicht einmal etwas weiß, das für die digitale Verarbeitung von grundlegender Bedeutung ist. Ich würde Quentin weiter ablehnen, weil er nicht in der Lage ist, den Humor zu verstehen, den Sie versucht haben.
Dunk
23
Wenn ich jede Antwort, die ich nicht verstand, ablehnen würde ... würde ich viele Antworten ablehnen.
Seamus
4
Hallo Andrew, es ist schon eine Weile her.
Tim Down
4
@ Tim: Gute Trauer, so hat es! Und wie geht es dem Bischof von Bermuda? (Habe ich mich richtig daran erinnert?) Ich denke, dieser Kommentarthread ist nicht der beste Ort, um aufzuholen ... 17 Jahre, nicht wahr?
Andrew Stacey
3
@ Cԃ ա ԃ "Diese Antwort ist fehlgeschlagen ..." seufzt . Sie haben gelesen, dass ich Mathematiker bin, nicht wahr? Diese Antwort funktioniert perfekt für einen sphärischen Programmierer im luftleeren Raum, daher weiß ich nicht, worüber Sie sich beschweren.
Andrew Stacey
35

Du könntest es tun

v = Math.abs(--v);

Das Dekrement setzt den Wert auf 0 oder -1 und Math.abskonvertiert dann -1 in +1.

Paul
quelle
27
Dies hat sich zu einem Wettbewerb zum Generieren von 10000 Möglichkeiten für eine einfache Aufgabe entwickelt. Und ich mag alle Wege, haha.
Josh
27
v = Math.round(Math.sin(Math.PI/(v+3)));
Benoit
15
@ Benoit - Ihre Formel ist gleich 1 für v = 0 und v = 1. DIESES ist allerdings richtig! v = Math.round(Math.cos(Math.PI/((v*2+1)+2)-2*v));: D
Teo.sk
2
Das würde den Wert niemals ändern. Wenn v = 1dann v = Math.Abs(-1)was ist +1. Wenn v = 0dann v = Math.Abs(-0)was ist 0.
Paul
1
+1 Und das war mein anderer ... Grr.
rekursiv
34

Im Allgemeinen können Sie den aktuellen Wert immer dann von der Summe der beiden Umschaltwerte abziehen, wenn Sie zwischen zwei Werten wechseln müssen:

    0,1 -> v = 1 - v
    1,2 -> v = 3 - v
    4,5 -> v = 9 - v 
Mouna Cheikhna
quelle
2
Das ist interessant und kreativ, aber potenziell gefährlich. Wenn es vbeschädigt wird, wechselt es plötzlich zwischen zwei verschiedenen Werten. (Nur etwas zu beachten ...)
Oosterwal
1
+1 für die interessante Idee. nicht, dass das OP oder irgendjemand anderes es unter diesen Umständen tatsächlich verwenden wird, aber diese Information sollte für immer irgendwo im Gehirn existieren.
Shimmy Weitzhandler
3
@oosterwal: Dann liegt das Problem sicherlich in der Korruption ...
GManNickG
@GManNickG: Früher oder später kommt es zu einer Beschädigung der Daten, daher müssen wir uns der Konsequenzen bewusst sein, wenn wir sie nicht erkennen. Wenn vnormalerweise zwei Zustände aus einer Liste von drei oder mehr Zuständen abwechselnd ausgeführt werden, kann eine Beschädigung von vdazu führen, dass das Programm abwechselnd zwei völlig unterschiedliche Zustände ausführt - dies kann zu unerwarteten und unerwünschten Ergebnissen führen. Die Lektion, die Sie daraus ziehen sollten, lautet: Führen Sie immer Plausibilitätsprüfungen für Ihre Daten durch.
Oosterwal
33

Wenn es die Ganzzahl 1 oder 0 sein muss, ist die Art und Weise, wie Sie es tun, in Ordnung, obwohl Klammern nicht benötigt werden. Wenn diese a als Boolesche Werte verwendet werden sollen, können Sie einfach Folgendes tun:

v = !v;
Michael Berkowski
quelle
10
Wird dies nicht dazu führen, dass Ollie's "v" auf ein boolesches Ergebnis gesetzt wird, nicht auf eine ganze Zahl?
Brian
12
Ja, das werde ich, und ich habe das im Satz über der Codezeile gewarnt. Wenn diese a als Boolesche Werte verwendet werden sollen
Michael Berkowski
23
v = v == 0 ? 1 : 0;

Reicht !

Nidhin
quelle
7
Mehr eine Meinung als eine Antwort, meinst du nicht auch?
Brian
16
@Brian: 'besser' dreht sich eigentlich alles um die Meinung.
Pimvdb
3
Mir gefällt, wie Sie die Klammern herausgenommen haben - das schneidet ein paar Zeichen ab!
Ollie Glass
9
@Brian: Die " Antwort " lautet "Nein, es gibt keine bessere Schreibweise v = (v==0 ? 1 : 0);" . Alle anderen finden unterschiedliche Möglichkeiten, Golf zu spielen. und die Frage nicht wirklich beantworten. Deshalb habe ich diese Antwort positiv bewertet.
Ian Boyd
19

Liste der Lösungen

Es gibt drei Lösungen, die ich vorschlagen möchte. Alle von ihnen wandeln jeden Wert 0(wenn 1, trueetc.) oder 1(wenn 0, false, nulletc.):

  • v = 1*!v
  • v = +!v
  • v = ~~!v

und eine weitere, bereits erwähnte, aber clevere und schnelle (obwohl nur für 0s und 1s funktioniert ):

  • v = 1-v

Lösung 1

Sie können die folgende Lösung verwenden:

v = 1*!v

Dadurch wird zuerst die Ganzzahl in den entgegengesetzten Booleschen Wert ( 0to Trueund einen anderen Wert to False) konvertiert und dann beim Multiplizieren mit als Ganzzahl behandelt 1. Infolgedessen 0wird in 1und jeder andere Wert in konvertiert 0.

Sehen Sie sich als Beweis diese jsfiddle an und geben Sie alle Werte an, die Sie testen möchten: jsfiddle.net/rH3g5/

Die Ergebnisse sind wie folgt:

  • -123wird in eine Ganzzahl konvertieren 0,
  • -10wird in eine Ganzzahl konvertieren 0,
  • -1wird in eine Ganzzahl konvertieren 0,
  • 0wird in eine Ganzzahl konvertieren 1,
  • 1wird in eine Ganzzahl konvertieren 0,
  • 2wird in eine Ganzzahl konvertieren 0,
  • 60wird in eine Ganzzahl konvertieren 0,

Lösung 2

Wie mblase75 feststellte, hatte jAndy eine andere Lösung, die wie meine funktioniert:

v = +!v

Es macht auch zuerst einen Booleschen Wert aus dem ursprünglichen Wert, verwendet ihn jedoch, +anstatt 1*ihn in eine Ganzzahl umzuwandeln. Das Ergebnis ist genau das gleiche, aber die Notation ist kürzer.

Lösung 3

Der andere Ansatz besteht darin, den ~~Operator zu verwenden :

v = ~~!v

Es ist ziemlich ungewöhnlich und wird immer von boolean in eine Ganzzahl konvertiert.

Tadeck
quelle
In JavaScript können Sie einer Variablen ein Präfix voranstellen +, um sie in eine Zahl umzuwandeln. +!vDies entspricht Ihrer Lösung (jAndys Lösung in den Kommentaren des OP).
Blazemonger
@ mblase75: Ja, Sie haben Recht, 1*das ersetzt werden kann, +wenn Sie versuchen, Boolesche Werte in Ganzzahlen umzuwandeln. Alles andere in meiner Antwort bleibt gleich. jAndys Antwort ist richtig, aber meine ist detaillierter. Ich werde seine / ihre Lösung zu meiner Antwort hinzufügen.
Tadeck
@Tadeck +1 für die schöne Idee.
Shimmy Weitzhandler
17

Um eine andere Antwort, einen Kommentar und meine eigene Meinung zusammenzufassen, schlage ich vor, zwei Dinge zu kombinieren:

  1. Verwenden Sie eine Funktion zum Umschalten
  2. Verwenden Sie innerhalb dieser Funktion eine besser lesbare Implementierung

Hier ist die Funktion, die Sie in eine Bibliothek einfügen oder in ein Plugin für ein anderes Javascript Framework einbinden können.

function inv(i) {
  if (i == 0) {
    return 1
  } else {
    return 0;
  }
}

Und die Verwendung ist einfach:

v = inv(v);

Die Vorteile sind:

  1. Keine Code-Duplizierung
  2. Wenn Sie oder jemand dies in Zukunft erneut lesen, werden Sie Ihren Code in kürzester Zeit verstehen.
Martin Schlagnitweit
quelle
Sind sie? Ich habe einen kurzen Test durchgeführt: jsperf.com/function-vs-no-function/2 und es scheint, dass der Unterschied nicht so groß ist.
Martin Schlagnitweit
25
7,5 ns gegen 8,8 ns. Diese zusätzlichen 1,3 Nanosekunden werden dich wirklich töten.
Ian Boyd
5
Mit all der Zeit, die ich gespart habe, habe ich meine Familie nach Disney World gebracht! :-)
Tom
1
Völlig richtig. Leute, die "clevere" Lösungen schreiben, mussten wahrscheinlich nie den Code "gems" anderer Programmierer pflegen
Avi
1
warum nicht function toggle(i){ return i == 0 ? 1 : 0 }?
Billy Moon
13

Ich weiß nicht, warum du deine eigenen Booleschen Werte bauen willst? Ich mag die funky Syntax, aber warum nicht verständlichen Code schreiben?

Dies ist nicht der kürzeste / schnellste, aber der klarste (und für alle lesbare) ist die Verwendung des bekannten if / else-Status:

if (v === 0)
{
  v = 1;
}
else
{
  v = 0;
}

Wenn Sie wirklich klar sein möchten, sollten Sie dafür Boolesche Werte anstelle von Zahlen verwenden. Sie sind für die meisten Fälle schnell genug. Mit Booleschen Werten können Sie einfach diese Syntax verwenden, die in Kürze gewinnt:

v = !v;
Mark Knol
quelle
1
Dies wäre eigentlich meine bevorzugte Antwort; Aber ternärer Operator gegen if-else ist ein heiliger Krieg, ich wollte die Zündschnur nicht anzünden. Das heißt, ich denke, die erste Zeile sollte sein === 0. Bei Sample-Eingabe von 7ist die richtige Ausgabe 0, dies wird jedoch ausgegeben 1.
Ian Boyd
4
Ist es sinnvoll, eine Eingabe wie 7 stillschweigend zu korrigieren, anstatt eine Ausnahme auszulösen? Ich meine, was ist, wenn ein anderes Stück Code die 7 in die Hände bekommt, wenn es nur 0 oder 1 erwartet, bevor Ihr Code den Wert korrigiert?
Chuck van der Linden
12

Eine andere Form Ihrer ursprünglichen Lösung:

v = Number(v == 0);

EDIT: Danke an TehShrike und Guffa, dass sie auf den Fehler in meiner ursprünglichen Lösung hingewiesen haben.

Kurt Kaylor
quelle
4
Der Operator == gibt unter vielen Systemen einen Booleschen Wert (anstelle einer Ganzzahl) zurück. Dies würde nur funktionieren, wenn v als Ganzzahl definiert wäre und die Sprache beim automatischen Umwandeln von Boolescher in Ganzzahl cool wäre.
TheShrike
Sehr richtig. Ich beantwortete die Frage im Kontext von Javascript (wie die Frage markiert wurde).
Kurt Kaylor
@ Kurt Kaylor: Javascript ist eines der Systeme, bei denen der Operator == einen Booleschen Wert zurückgibt, sodass er nicht das Gleiche wie die ursprüngliche Lösung tut.
Guffa
@Guffa: Ich nutze die Tatsache, dass Javascript eine schwach typisierte Sprache mit impliziter Typkonvertierung ist (zB'0.0000 '== 0, 0 == "", false == "", false == 0, 1 == wahr, etc). Ich kann den zurückgegebenen booleschen Wert genauso verwenden wie eine Ganzzahl mit dem Wert 0 oder 1. Wenn Sie beispielsweise "2 + true" in einer Javascript-Konsole auswerten, erhalten Sie 3.
Kurt Kaylor
1
@ Kurt Kaylor: Das funktioniert nur in Situationen, in denen Sie eine implizite Konvertierung erzwingen. Versuchen Sie es zum Beispiel 'opacity:'+trueund Sie landen mit opacity:truestatt opacity:1.
Guffa
11

Ich würde es expliziter machen.

Was heißt vdas

Zum Beispiel, wenn v ein Zustand ist. Erstellen Sie einen Objektstatus. In DDD ein Wertobjekt.

Implementieren Sie die Logik in diesem Wertobjekt. Dann können Sie Ihren Code auf eine funktionalere und besser lesbare Weise schreiben. Der Statuswechsel kann durch Erstellen eines neuen Status basierend auf dem aktuellen Status erfolgen. Ihre if-Anweisung / Logik wird dann in Ihr Objekt eingekapselt, was Sie unittest können. Ein valueObject ist immer unveränderlich, hat also keine Identität. Um den Wert zu ändern, müssen Sie einen neuen erstellen.

Beispiel:

public class Status
{
    private readonly int _actualValue;
    public Status(int value)
    {
        _actualValue = value;
    }
    public Status(Status status)
    {
        _actualValue = status._actualValue == 0 ? 1 : 0; 
    }

    //some equals method to compare two Status objects
}

var status = new Status(0);

Status = new Status(status);
Marco
quelle
6
über Engineering?
Alejandro5042
6
+1 für mich zum Lachen bringen
Denshi
10

Ein anderer Weg, es zu tun:

v = ~(v|-v) >>> 31;
Eng.Fouad
quelle
10

Dies fehlt:

v = [1, 0][v];

Es funktioniert auch als Round Robin:

v = [2, 0, 1][v]; // 0 2 1 0 ...
v = [1, 2, 0][v]; // 0 1 2 0 ...
v = [1, 2, 3, 4, 5, 0][v]; // 0 1 2 3 4 5 ...
v = [5, 0, 1, 2, 3, 4][v]; // 0 5 4 3 2 1 0 ...

Oder

v = {0: 1, 1: 0}[v];

Das Charme der letzten Lösung ist, dass es auch mit allen anderen Werten funktioniert.

v = {777: 'seven', 'seven': 777}[v];

Für einen ganz besonderen Fall, wenn Sie einen (sich ändernden) Wert erhalten undefinedmöchten, kann dieses Muster hilfreich sein:

v = { undefined: someValue }[v]; // undefined someValue undefined someValue undefined ...
Nina Scholz
quelle
9

Da dies JavaScript ist, können wir das Unäre verwenden +, um in int zu konvertieren:

v = +!v;

Dies wird NOTden Wert von v(Geben von trueif v == 0oder falseif v == 1) logisch . Dann konvertieren wir den zurückgegebenen booleschen Wert in die entsprechende Ganzzahldarstellung.

0x499602D2
quelle
8

Nur zum Spaß: v = Math.pow(v-1,v)Schaltet auch zwischen 1 und 0 um.

Blazemonger
quelle
7

Einer noch: v=++v%2

(in C wäre es einfach ++v%=2)

ps. Ja, ich weiß, dass es sich um eine doppelte Zuweisung handelt, aber dies ist nur eine rohe Umschreibung der C-Methode (die nicht so funktioniert, wie sie ist, da der JS-Vorinkrementierungsoperator keinen Wert zurückgibt.

Adam Jurczyk
quelle
3
Ihre C-Version ist illegal. Sie können das Ergebnis eines ++Operators nicht ändern (es ist kein l-Wert). Was v=++v%2, Sie modifizieren vzweimal. Ich weiß nicht, ob das in JavaScript gut definiert ist, aber es ist nicht notwendig. v = (v+1) % 2.
Keith Thompson
Zumindest c++darin - weil der Vorinkrementierungsoperator eine höhere Priorität hat und die Variable 'an Ort und Stelle' ändert, kann sie als l-Wert verwendet werden. Ich denke, dass die JS-Implementierung von so ++ist, dass sie nicht als Wert behandelt werden kann: / Und ja, das ist überflüssig, aber ich habe versucht, nur eine andere Methode zu zeigen - es gibt bereits bessere Lösungen :)
Adam Jurczyk
3
+1. Kann geschrieben werden als v = (v + 1)% 2.
Niktrs
7

Wenn Sie sicher sind, dass Ihre Eingabe entweder eine 1 oder eine 0 ist, können Sie Folgendes verwenden:

v = 2+~v;
brandx
quelle
7

Definieren Sie ein Array {1,0}, setzen Sie v auf v [v], daher wird v mit einem Wert von 0 zu 1 und umgekehrt.

S ..
quelle
Meine Lösung ist richtig, wenn Sie es nicht mögen, schreiben Sie warum. Ihr Kommentar hilft niemandem. Meine Lösung liest eine Variable, anstatt eine Entscheidung zu treffen. Dies erfordert weniger CPU.
S ..
5

Eine andere kreative Art, dies zu tun, bei vder jeder Wert gleich ist, wird immer zurückkehren 0oder1

v = !!v^1;
Yanick Rochon
quelle
3
zwei !!führen zu nichts in der logischen Mathematik, Sie können !!!!dort eingeben und werden gleich sein, aber resultieren 4 nicht benötigte Operationen
Alex K
10
@Alex: !!wird in einen Bool umgewandelt. !!(1) === trueund!!(0) === false
Nickf
1
@nickf: aha, also ich denke, v = Boolean(v^1)wäre informativer, danke für die Erklärung - dachte nicht über Casting nach
Alex K
1
@ Alex, "logische Mathematik"? Deshalb sind Mathematiker schlechte Programmierer. Versteh mich nicht falsch; Gute Programmierer verstehen auch gut Mathematik. Das hat aber nichts mit logischer Mathematik zu tun. Es ist ein Sprachkonstrukt, das bei jedem Ausdruck, zumindest in Javascript, !in Boolesche Werte umgewandelt wird. Durch Hinzufügen eines weiteren !wird dieser Boolesche Wert negiert. Das Casting ist hier implizit und das Endergebnis funktioniert. Das -1 ist nicht erforderlich.
Yanick Rochon
1
Ich bin überhaupt kein Mathematiker. Sie können dies versuchen und sich selbst sehen jsperf.com/javascript-boolean-test
Alex K
4

Wenn mögliche Werte für v nur 0 und 1 sind, dann für jede ganze Zahl x der Ausdruck: v = Math.pow ((Math.pow (x, v) - x), v); schaltet den Wert um.

Ich weiß, dass dies eine hässliche Lösung ist und das OP nicht danach gesucht hat ... aber ich habe nur über eine andere Lösung nachgedacht, als ich auf dem Klo war: P.

Amit
quelle
3
v=!v;

funktioniert für v = 0 und v = 1; und den Staat umschalten;

Lehrer
quelle
1

Wenn es nur zwei Werte gibt, wie in diesem Fall (0, 1), halte ich es für verschwenderisch, int zu verwenden. Entscheide dich lieber für Boolesche Werte und arbeite in Bits. Ich weiß, ich gehe davon aus, aber im Falle eines Wechsels zwischen zwei Zuständen scheint Boolescher Wert die ideale Wahl zu sein.

Bernstein
quelle
1

Nun, wie wir wissen, liefert nur dieser boolesche Vergleich in Javascript auch das erwartete Ergebnis.

dh v = v == 0reicht dafür.

Unten ist der Code dafür:

var v = 0;
alert("if v  is 0 output: " + (v == 0));

setTimeout(function() {
  v = 1;
  alert("if v  is 1 Output: " + (v == 0));
}, 1000);

JSFiddle: https://jsfiddle.net/vikash2402/83zf2zz0/

Ich hoffe das hilft dir :)

Vikash Pandey
quelle
Das funktioniert zum Umschalten eines Wertes, aber der Wert wechselt nicht zwischen 0 und 1, sondern zwischen trueund false. Sie können verwenden v == 0, um den Wert der Variablen in einer Bedingung zu bestimmen, aber wenn Sie den Wert 0 oder 1 verwenden möchten, müssen Sie etwas wie v == 0 ? 0 : 1oder verwenden Number(v), um dies zu erhalten. (Sie können auch verwenden, v = !v;um zwischen trueund false
umzuschalten
Ja, ich habe es verstanden. Danke :)
Vikash Pandey
0

v = Zahl (! ​​v)

Der invertierte boolesche Wert wird in Number umgewandelt, was die gewünschte Ausgabe ist.

Rohit Goyal
quelle