So tauschen Sie zwei Variablen in JavaScript aus


Antworten:


321

Hier ist ein Einzeiler, um die Werte zweier Variablen auszutauschen.
Gegebene Variablen aund b:

b = [a, a = b][0];

Demonstration unten:

var a=1,
    b=2,
    output=document.getElementById('output');

output.innerHTML="<p>Original: "+a+", "+b+"</p>";

b = [a, a = b][0];

output.innerHTML+="<p>Swapped: "+a+", "+b+"</p>";
<div id="output"></div>


264
+1. Die kürzeste Version wird jedoch in ECMAScript 6 enthalten sein : [a, b] = [b, a];.
dfsq

8
@ Kay: Es scheint auch viel langsamer zu sein, ein Array anstelle einer dritten Variablen zu verwenden: http://jsperf.com/swap-array-vs-variable Ich habe dies jedoch nur in Chrome getestet. Ich konnte die ECMAScript 6-Version noch nicht testen, da derzeit ein Invalid left-hand side in assignment Fehler auftritt.
Nein,

2
@ FrançoisWahl Guter Punkt. Ich denke, die meisten Antworten hier werden funktionieren und sind ziemlich gleichwertig. Ich nehme an, es ist ein Kompromiss zwischen temporärer variabler Verwendung, Codemenge und Geschwindigkeit.
Showdev

3
@ FrançoisWahl gut, ich hätte nicht gedacht, dass diese Lösung so viel langsamer war. Siehe auch: jsperf.com/swap-array-vs-variable/3
kay - SE ist böse

3
@showdev Lesen Sie das Dijkstra-Zitat in Ted Hopps Antwort.
Brian McCutchon

185

ES6 (Firefox und Chrome unterstützen es bereits (Destructuring Assignment Array Matching)):

let a = 5, b = 6;
[a, b] = [b, a];
console.log(`${a} ${b}`);


2
kennt jemand den Namen eines solchen Swaps in es6?
Derek

6
@derek - Ich denke, es heißt Array Matching , eine Form der Destrukturierungszuweisung .
Ted Hopp

4
Dies scheint ungefähr 35-mal langsamer zu sein als die dritte variable Methode unter NodeJS 7.4.0 / Win7 64. Aber es ist sicher ordentlich.
Mkey


5
Seit V8 Version 6.8 sollte das Austauschen von Variablen mit Array-Destrukturierung genauso schnell sein wie mit einer temporären Variablen ( v8project.blogspot.com/2018/06/v8-release-68.html ).
Ruben Verborgh

120

Du kannst das:

var a = 1,
    b = 2,
    tmp;
tmp = a;
a = b;
b = tmp;

Aus Gründen der Lesbarkeit und Wartbarkeit ist dies nicht zu übertreffen (zumindest in JavaScript). Jeder, der den Code verwaltet (einschließlich Sie in sechs Monaten), weiß genau, was los ist.

Da es sich um Ganzzahlen handelt, können Sie auch eine beliebige Anzahl cleverer Tricks anwenden 1 verwenden , um ohne Verwendung einer dritten Variablen zu tauschen. Zum Beispiel können Sie den bitweisen xor-Operator verwenden:

let a = 1, b = 2;
a = a ^ b;
b = a ^ b;
a = a ^ b;
    
console.log('a is now:', a);
console.log('b is now:', b);

Dies wird als XOR-Swap-Algorithmus bezeichnet. Seine Betriebstheorie wird in diesem Wikipedia-Artikel beschrieben .

1 "Der kompetente Programmierer ist sich der begrenzten Größe seines eigenen Schädels voll bewusst. Er geht seine Aufgabe daher mit voller Demut an und vermeidet clevere Tricks wie die Pest." - Edsger W. Dijkstra


Xor funktioniert mit jedem Datentyp. Es ist der Subtraktionstrick, der nur mit Zahlen funktioniert.
Rob Grant

11
@RobertGrant - Der xor-Operator in JavaScript konvertiert seine Operanden in 32-Bit-Ganzzahlen (mithilfe der ToInt32internen Methode - siehe Abschnitt 11.10 des ECMAScript-Standards ). Es werden nicht die richtigen Ergebnisse für nicht ganzzahlige numerische Werte erzeugt. Es konvertiert auch nicht numerische Werte in 32-Bit-Ganzzahlen. Wenn Sie mit a = "hi"und beginnen b = "there", enden Sie mit a == 0und b == 0.
Ted Hopp

1
Dieser Trick funktioniert mit jedem Datentyp, vorausgesetzt, Sie haben nichts gegen ein ganzzahliges Ergebnis. Die Werte werden automatisch in int32s umgewandelt. Dies bedeutet, dass es mit numerischen Zeichenfolgen, Booleschen Werten (0/1), Null (0) und leeren Arrays / Objekten (0) arbeiten kann. Obwohl der ursprüngliche Typ nicht beibehalten wird, würden betroffene Boolesche Werte beispielsweise nicht mit typeof a == 'boolean'oder funktionieren a === false. Reelle Zahlen funktionieren, außer dass sie gegen Null oder auf die nächste ganze Zahl gerundet sind.
Beejor

1
@Beejor - Mit anderen Worten, es funktioniert mit jedem Datentyp, außer nicht (es sei denn, es handelt sich um ganzzahlige Werte). In meinem Buch bedeutet "Swap" "Ende mit jeder Variablen mit dem Wert, den die andere hatte", nicht "In int32 konvertieren und dann Swap".
Ted Hopp

@ TedHopp Fair genug. Ich meinte "funktioniert" in Bezug auf die Tatsache, dass Sie jeden Datentyp darauf werfen können, nicht so, wie es als gute Swap-Lösung funktioniert. Ich bin damit einverstanden, dass es im Allgemeinen nicht sehr nützlich ist.
Beejor

58

Verwenden Sie nicht den folgenden Code. Es ist nicht die empfohlene Methode, die Werte zweier Variablen auszutauschen (verwenden Sie einfach eine temporäre Variable ). Es zeigt nur einen JavaScript-Trick.

Diese Lösung verwendet keine temporären Variablen, keine Arrays, nur eine Addition und ist schnell . Tatsächlich ist es auf mehreren Plattformen manchmal schneller als eine temporäre Variable .
Es funktioniert für alle Zahlen, läuft nie über und verarbeitet Randfälle wie Infinity und NaN.

a = b + (b=a, 0)

Es funktioniert in zwei Schritten:

  • (b=a, 0)setzt bauf den alten Wert von aund ergibt0
  • a = b + 0setzt aauf den alten Wert vonb

5
Die temporäre Var-Version ist etwas schneller und allgemeiner und lesbarer. jsperf.com/swap-two-numbers-without-tmp-var/9
Antimon

Was bedeutet diese () Syntax überhaupt? Wie ergibt es 0?
Pete Alvin

8
Der Operator in Klammern ist der Kommaoperator ,und wurde umbrochen, um das Vorrangrecht festzulegen. Der Kommaoperator wertet beide Argumente aus (in diesem Fall b=aund 0) und gibt das letzte (in diesem Fall 0) zurück. Hier hat es also den Effekt, das Neue bauf den alten Wert von zu setzen aund gleichzeitig nachzugeben 0.
Ruben Verborgh

6
Habe ich Recht, wenn ich denke, dass dies nur für numerische Werte funktioniert? Sie können dies nicht mit zB var a = "Hallo" b = "Welt" als a = "Welt0" verwenden.
Chris GW Green

3
@ ChrisGWGreen:a = b + (b=a, "")

19

Seit ES6 können Sie Variablen auch eleganter austauschen:

var a = 1,
    b = 2;

[a, b] = [b, a];

console.log('a:', a, 'b:', b); // a: 2 b: 1

18

Hier ist ein Einzeiler, der davon ausgeht aund bbereits existiert und Werte hat, die ausgetauscht werden müssen:

var c=a, a=b, b=c;

Wie @Kay bereits erwähnt hat, ist dies tatsächlich besser als das Array (fast 2x so schnell).


1
Wie meine ideale Antwort ziehe ich es vor, die Variablen a & b beim Tauschen nicht neu zu deklarieren und den expliziten Variablennamen "tmp" zu verwenden. Wie : var a, b, tmp; a = 1; b = 2;; tmp=a, a=b, b=tmp; Persönlicher Geschmack.
Johnny Wong

10

Verwenden Sie eine dritte Variable wie folgt:

var a = 1,
    b = 2,
    c = a;

a = b; // must be first or a and b end up being both 1
b = c;

DEMO - Verwenden einer dritten Variablen



10

ES6 + -Methode: Seit ES6 können Sie Variablen eleganter austauschen. Sie können den Matching-Zuordnungsarray-Abgleich verwenden. Es ist einfach. var a = 10 b = 20;

[a, b] = [b, a]

console.log (a, b) // 20 10



9

Sie können eine temporäre Swap-Variable oder XOR verwenden.

a = a ^ b
b = a ^ b
a = a ^ b

Dies ist nur ein grundlegendes logisches Konzept und funktioniert in jeder Sprache, die den XOR-Betrieb unterstützt.

Bearbeiten: siehe Kommentare. Ich habe vergessen zu sagen, dass dies mit Sicherheit nur mit Ganzzahlen funktioniert. Angenommen, die ganzzahligen Variablen stammen aus dem Thread der Frage


16
Funktioniert zum Programmieren von Interviews und anderen allgemeinen Trivia-Fällen. Beachten Sie jedoch, dass dies eine ziemlich dumme Methode ist, um Werte im wirklichen Leben auszutauschen. Zum einen funktioniert es in JS nur mit ganzen Zahlen.
CHao

1
@ Kay Was meinst du mit "seit 30 Jahren keine echte Sache mehr?" Ich benutze bitweise Operatoren, wann immer es Sinn macht, was eigentlich ziemlich häufig ist (zum Beispiel das Umschalten eines unbekannten Booleschen Werts)
Ben Harold

1
@cHao Bitwise Operator ist durchweg (und bei weitem) der schnellste auf meinem Computer: jsperf.com/swap-array-vs-variable/2
Ben Harold

3
@php_surgeon Ich habe die Geige ein wenig geändert, damit der Compiler die Variablen nicht als tot markieren kann. jsperf.com/swap-array-vs-variable/3 . Die Temp-Var-Lösung ist jetzt 1/4 schneller als die XOR-Swap-Lösung
Kay - SE ist böse

1
@Kay In Situationen, in denen etwas stabil, gut kommentiert, die schnellste Technik und nur an ein oder zwei Stellen verwendet wird, verstehe ich nicht, warum es im Produktionscode nicht in Ordnung wäre. Bitweise Operationen sind im Allgemeinen ein schwieriges Konzept. Wenn der Code bereits einige davon verwendet, müssen die Betreuer mit ihnen ohnehin vertraut sein. In den meisten Fällen ist es offensichtlich übertrieben. Ich denke nur, dass pauschale Aussagen nicht immer hilfreich sind. Alles hat einen Platz, sogar "goto" und "eval".
Beejor


7

Da Ihre Frage wertvoll war "Nur diese Variablen, keine Objekte.", Ist die Antwort auch wertvoll:

var a = 1, b = 2

a=a+b;
b=a-b;
a=a-b;

Es ist ein Trick.

Und wie Rodrigo Assis sagte, kann es "kürzer sein".

 b=a+(a=b)-b;

Demo: http://jsfiddle.net/abdennour/2jJQ2/


1
Gleiche Fehler wie die Antwort von @ DmiN.
kay - SE ist böse

Wo finden Sie Fehler? Es ist nicht ehrenwert
Abdennour TOUMI

2
@AbdennourToumi Ich denke, Kay bezieht sich auf die Tatsache, dass Ihre Antwort nur mit ganzen Zahlen funktioniert.
showdev

1
@showdev: Bitte lesen Sie noch einmal Frage: "Nur diese Variablen, keine Objekte" .... meine Antwort ist als Frage wertvoll. Ich bitte Sie, den Kommentar zu kennzeichnen. Ich wiederhole: Es ist nicht ehrenwert.
Abdennour TOUMI

1
Dieses Gespräch ist bizarr. @AbdennourTOUMI - Variablen sind nicht dasselbe wie Ganzzahlen. Sie können Variablen haben, die auf Objekte, Zeichenfolgen, Funktionen, Null usw. verweisen.
Rob Grant

6

ES6-Destrukturierung:

Verwenden eines Arrays: [a, b] = [b, a]; // my favorite

Verwenden eines Objekts: {a, b} = {a:b, b:a}; // not bad neither


4

Wie könnten wir diese klassischen Oneliner vermissen?

var a = 1, b = 2
a = ({a:b, _:(b=a)}).a;

Und

var a = 1, b = 2
a = (_=b,b=a,_);

Die letzte macht die globale Variable '_' verfügbar, aber das sollte keine Rolle spielen, da die typische Javascript-Konvention darin besteht, sie als Variable 'dont care' zu verwenden.


1
Im zweiten ist ein Tippfehler. Es sollte seina = (_=b,b=a,_);
Mageek

Was bedeutet der Unterstrich _? Warum braucht es keine Erklärung?
Tag

Der Unterstrich ist nur ein globaler Variablenname. Sie können ihn durch einen gültigen ersetzen. zB a = (justsomething = b, b = a, justsomething)
Teemu Ikonen

6
Oh nein, benutze keine nicht deklarierten magisch-globalen Vars! Das ist ein sicherer Weg zu schrecklichen Fehlern im wirklichen Leben.
Oriadam

Jeder, der underscore.js verwendet, wird sehr unglücklich sein, wenn er den zweiten versucht.
Ted Hopp

3

Ich sehe hier eine Art Programmierolympiade. Noch eine knifflige einzeilige Lösung:

b = (function(){ a=b; return arguments[0]; })(a);

Geige: http://jsfiddle.net/cherniv/4q226/


2
Keine Notwendigkeit, die langsame zu verwenden arguments, tun Sie es einfach b = (function (x){ return x; })(a, a=b).
Ruben Verborgh

1
@ RubenVerborgh ja, aber mit Argumenten definieren wir keine dritte Variable!
Cherniv

1
Technisch gesehen argumentswäre die Liste auch eine Variable.
Ruben Verborgh

1
Nun, Sie weisen es azu, arguments[0]indem Sie es als Parameter übergeben.
Ruben Verborgh

1
@ RubenVerborgh ja, aber Sie erstellen das nicht argumentsund seine Zuordnung geschieht "hinter den Kulissen"
Cherniv


3
var a = 5;
var b = 10;

b = [a, a = b][0];
//or
b = [a, a = b];
b = b[0];

//or
b = [a, b];
a = b[1];
b = b[0];


alert("a=" + a + ',' + "b=" + b);

Entfernen oder kommentieren Sie die 2 // oder und führen Sie sie mit dem einen Satz Code aus

http://jsfiddle.net/USdv8/57/


2

Wir können var wie folgt tauschen:

var val1 =  117,
    val2 = 327;

val2 = val1-val2; 
console.log(val2);
val1 = val1-val2;
console.log(val1);
val2 = val1+val2;
console.log(val2);

2

In ES6 gibt es jetzt eine Destrukturierungszuweisung und Sie können Folgendes tun:

let a = 1;
let b = 2;
[b, a] = [a, b]  // a = 2, b = 1

1
let a = 2, b = 4;
[b, a] = [a, b];

Ein ausführlicherer Ansatz wäre

let a = 2, b = 4;
a = [a, b];
b = a[0];
a = a[1];


1

Bis ES5 müssen Sie zum Auswechseln von zwei Zahlen eine temporäre Variable erstellen und diese dann austauschen. In ES6 ist es jedoch sehr einfach, zwei Zahlen mithilfe der Array-Destrukturierung auszutauschen. Siehe Beispiel.

let x,y;
[x,y]=[2,3];
console.log(x,y);      // return 2,3

[x,y]=[y,x];
console.log(x,y);      // return 3,2

1

Weil ich höre, dass diese Methode langsamer läuft:

b = [a, a = b][0];

Wenn Sie Ihre Variablen in einem Objekt (oder Array) speichern möchten, sollte diese Funktion funktionieren:

function swapVars(obj, var1, var2){
    let temp = obj[var1];
    obj[var1] = obj[var2];
    obj[var2] = temp;
}

Verwendung:

let test = {a: 'test 1', b: 'test 2'};

console.log(test); //output: {a: 'test 1', b: 'test 2'}

swapVars(test, 'a', 'b');

console.log(test); //output: {a: 'test 2', b: 'test 1'}

1

Wir können das IIFE verwenden, um zwei Werte ohne zusätzlichen Parameter auszutauschen

var a = 5, b =8;
b = (function(a){ 
    return a 
}(a, a=b));

document.write("a: " + a+ "  b:  "+ b);


1

Die ES6-Array-Destrukturierung wird verwendet, um zwei Variablen auszutauschen. Siehe Beispiel

var [x,y]=[1,2];
[x,y]=[y,x];

Einfacher Weg möglich mit:

x === 1und y === 2; Aber nach der Destrukturierung xist y, dh 2und yist x, dh 1.


1

Mit Bitwise tauschen

let a = 10;
let b = 20;
a ^= b;
y ^= a;
a ^= b;

Einzeiliger Swap "using Array"

[a, b] = [b, a]

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.