Come scambiare due variabili in JavaScript


Risposte:


321

Ecco un one-liner per scambiare i valori di due variabili.
Variabili date ae b:

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

Dimostrazione di seguito:

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. Ma la versione più breve sarà in ECMAScript 6: [a, b] = [b, a];.
dfsq,

8
@Kay: Sembra anche molto più lento usare un array invece di una terza variabile: http://jsperf.com/swap-array-vs-variable L' ho provato solo su Chrome. Non sono stato ancora in grado di testare la versione ECMAScript 6 in quanto attualmente fornisce un Invalid left-hand side in assignment errore.
No, il

2
@ FrançoisWahl Un buon punto. Penso che la maggior parte delle risposte qui funzionerà e sono abbastanza equivalenti. Suppongo che sia un compromesso tra uso variabile temporaneo, quantità di codice e velocità.
showdev,

3
@ FrançoisWahl bene, non avrei immaginato che questa soluzione fosse molto più lenta. Vedi anche: jsperf.com/swap-array-vs-variable/3
kay - SE is evil

3
@showdev Leggi la citazione di Dijkstra nella risposta di Ted Hopp.
Brian McCutchon,

185

ES6 (Firefox e Chrome già lo supportano (Destructuring Assignment Array Matching)):

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


2
qualcuno conosce il nome di questo tipo di scambio in es6?
Derek,

6
@derek - Penso che si chiami array array , una forma di assegnazione destrutturante .
Ted Hopp,

4
Questo sembra essere circa 35 volte più lento del terzo metodo variabile su nodejs 7.4.0 / win7 64. Ma di sicuro è pulito.
mkey


5
Dalla versione 6.8 di V8, lo scambio di variabili con la distruzione dell'array dovrebbe essere rapido come con una variabile temporanea ( v8project.blogspot.com/2018/06/v8-release-68.html ).
Ruben Verborgh,

120

Puoi farlo:

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

Per leggibilità e manutenibilità, questo non può essere battuto (almeno in JavaScript). Chiunque mantenga il codice (incluso te tra sei mesi) saprà esattamente cosa sta succedendo.

Dato che si tratta di numeri interi, è anche possibile utilizzare qualsiasi numero di trucchi intelligenti 1 per scambiare senza utilizzare una terza variabile. Ad esempio è possibile utilizzare l'operatore xor bit a bit:

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);

Questo è chiamato l'algoritmo di scambio XOR. La sua teoria del funzionamento è descritta in questo articolo di Wikipedia .

1 "Il programmatore competente è pienamente consapevole delle dimensioni limitate del proprio cranio. Si avvicina quindi al suo compito con piena umiltà ed evita trucchi intelligenti come la peste." - Edsger W. Dijkstra


Xor funzionerà con qualsiasi tipo di dati. È il trucco di sottrazione che funziona solo con i numeri.
Rob Grant,

11
@RobertGrant - L'operatore xor in JavaScript converte i suoi operandi in numeri interi a 32 bit (utilizzando il ToInt32metodo interno, vedere la Sezione 11.10 dello standard ECMAScript ). Non produce i risultati corretti per valori numerici non interi. Converte anche valori non numerici in numeri interi a 32 bit. Se inizi con a = "hi"e b = "there", finisci con a == 0e b == 0.
Ted Hopp,

1
Questo trucco funziona con qualsiasi tipo di dati, a condizione che non ti dispiaccia un risultato intero; i valori vengono automaticamente castati a int32s. Ciò significa che può funzionare con stringhe numeriche, booleane (0/1), null (0) e matrici / oggetti vuoti (0). Sebbene il tipo originale non sia conservato, i booleani interessati non funzionerebbero typeof a == 'boolean'o a === false, ad esempio. I numeri reali funzionano, tranne per il fatto che sono spostati verso zero rispetto a arrotondati all'intero più vicino.
Beejor,

1
@Beejor - In altre parole, funziona con qualsiasi tipo di dati, tranne che non lo è (a meno che non siano valori interi). Nel mio libro "scambio" significa "fine con ogni variabile che ha il valore che aveva l'altro", non "convertire in int32 e quindi scambiare".
Ted Hopp,

@TedHopp Abbastanza giusto. Intendevo "funziona" in termini di fatto che puoi lanciare qualsiasi tipo di dato, non come funziona come una buona soluzione di scambio. Sono d'accordo che non è molto utile in generale.
Beejor,

58

Non utilizzare il codice qui sotto. È non il metodo consigliato per scambiare i valori di due variabili (semplicemente utilizzare una variabile temporanea per questo). Mostra solo un trucco JavaScript.

Questa soluzione non utilizza variabili temporanee, matrici, solo un'aggiunta ed è veloce . In effetti, a volte è più veloce di una variabile temporanea su più piattaforme .
Funziona con tutti i numeri, non trabocca mai e gestisce casi limite come Infinity e NaN.

a = b + (b=a, 0)

Funziona in due passaggi:

  • (b=a, 0)imposta bsul vecchio valore di ae cede0
  • a = b + 0imposta asul vecchio valore dib

5
La versione temp var è leggermente più veloce, più generale e anche più leggibile. jsperf.com/swap-two-numbers-without-tmp-var/9
Antimonio

Cosa significa anche questa () sintassi? come produce 0?
Pete Alvin,

8
L'operatore tra parentesi è l'operatore virgola ,ed è stato racchiuso per impostare la precedenza a destra. L'operatore virgola valuta entrambi i suoi argomenti (in questo caso b=ae 0) e restituisce l'ultimo (in questo caso 0). Quindi qui, ha l'effetto di impostare il nuovo bsul vecchio valore di a, mentre cede 0.
Ruben Verborgh,

6
Ho ragione nel pensare che questo funziona solo per un valore numerico? Non puoi usarlo con es. Var a = "hello" b = "world" come a = "world0".
Chris GW Green,

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

19

Da ES6, puoi anche scambiare le variabili in modo più elegante:

var a = 1,
    b = 2;

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

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

18

Ecco un one-liner, supponendo ache besistano già e che abbiano valori che devono essere scambiati:

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

Come accennato da @Kay, questo in realtà funziona meglio del modo array (quasi il doppio della velocità).


1
Come la mia risposta ideale, preferisco non ripetere la dichiarazione della variabile a & b durante lo scambio e usare il nome della variabile esplicita "tmp". Come var a, b, tmp; a = 1:; b = 2; tmp=a, a=b, b=tmp; Gusto personale.
Johnny Wong,

10

Usa una terza variabile come questa:

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

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

DEMO - Utilizzo di una terza variabile



10

Metodo ES6 +: da ES6, è possibile scambiare le variabili in modo più elegante. È possibile utilizzare la corrispondenza dell'array di assegnazioni destrutturanti. È semplicemente. var a = 10 b = 20;

[a, b] = [b, a]

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


10

Ora puoi finalmente fare:

let a = 5;
let b = 10;

[a, b] = [b, a]; // ES6

console.log(a, b);


9

È possibile utilizzare una variabile di scambio temporanea o XOR.

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

Questo è solo un concetto logico di base e funziona in tutte le lingue che supportano il funzionamento di XOR.

modifica: vedi i commenti. Hai dimenticato di dire che questo funziona sicuramente solo con numeri interi. Presuppone le variabili intere dal thread della domanda


16
Lavora per le interviste di programmazione e altri casi generali. Nota, tuttavia, questo è un modo piuttosto stupido di scambiare valori nella vita reale. Per prima cosa, in JS, funziona solo con numeri interi.
cHao,

1
@Kay Cosa intendi con "non è una cosa reale negli ultimi 30 anni?" Uso gli operatori bit a bit ogni volta che ha senso, il che in realtà è abbastanza spesso (alternare un booleano sconosciuto, per esempio)
Ben Harold,

1
@cHao L'operatore Bitwise è costantemente (e di gran lunga) il più veloce sulla mia macchina: jsperf.com/swap-array-vs-variable/2
Ben Harold

3
@php_surgeon Ho cambiato un po 'il violino in modo che il compilatore non possa contrassegnare le variabili come morte. jsperf.com/swap-array-vs-variable/3 . La soluzione temp var è ora 1/4 più veloce della soluzione di scambio xor
kay - SE è male

1
@Kay In situazioni in cui qualcosa è stabile, ben commentato, la tecnica più veloce e utilizzata solo in uno o due posti, non vedo perché non vada bene nel codice di produzione. Le operazioni bit a bit in generale sono un concetto difficile, quindi se il codice ne utilizza già un mucchio, i manutentori dovrebbero comunque conoscerli. Nella maggior parte dei casi, è ovviamente eccessivo. Penso solo che le dichiarazioni generali non siano sempre utili; tutto ha un posto, anche "goto" e "eval".
Beejor,


7

Poiché la tua domanda era preziosa "Solo queste variabili, non alcun oggetto", anche la risposta sarà preziosa:

var a = 1, b = 2

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

è un trucco

E come diceva Rodrigo Assis, "può essere più breve"

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

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


1
Stessi difetti della risposta di @ DmiN.
kay - SE è malvagio il

dove trovi i difetti? Non è onorevole
Abdennour TOUMI

2
@AbdennourToumi Penso che Kay si riferisca al fatto che la tua risposta funziona solo con numeri interi.
showdev,

1
@showdev: Ti preghiamo di leggere di nuovo la domanda: "Solo queste variabili, non gli oggetti" .... la mia risposta è preziosa come una domanda. Ti chiedo di contrassegnare il commento. Ripeto: non è onorevole.
Abdennour TOUMI

1
Questa conversazione è bizzarra. @AbdennourTOUMI - le variabili non sono uguali agli interi. Puoi avere variabili che puntano a oggetti, stringhe, funzioni, null, ecc.
Rob Grant,

6

ES6 Destructuring:

Utilizzando un array: [a, b] = [b, a]; // my favorite

Utilizzando un oggetto: {a, b} = {a:b, b:a}; // not bad neither


4

Come potremmo perdere questi classici oneliner

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

E

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

L'ultimo espone la variabile globale '_' ma ciò non dovrebbe importare come tipica convenzione javascript è usarla come variabile 'non importa'.


1
C'è un errore di battitura nel secondo. Dovrebbe esserea = (_=b,b=a,_);
Mageek,

Cosa significa il carattere di sottolineatura _? Perché non ha bisogno di una dichiarazione?
giorno

il carattere di sottolineatura è solo un nome di variabile globale, è possibile sostituirlo con uno valido. es. a = (justsomething = b, b = a, justsomething)
Teemu Ikonen

6
Oh no, non usare vars magico-globali non dichiarati! Questo è un modo sicuro per orribili bug nella vita reale.
Oriadam,

Chiunque utilizzi underscore.js sarà molto infelice se prova il secondo.
Ted Hopp,

3

Vedo un po 'di olimpiadi di programmazione qui. Un'altra soluzione complicata a una riga:

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

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


2
Non c'è bisogno di usare il lento arguments, basta farlo b = (function (x){ return x; })(a, a=b).
Ruben Verborgh,

1
@RubenVerborgh sì, ma con argomenti non stiamo definendo una terza variabile!
Cherniv,

1
Tecnicamente, l' argumentselenco sarebbe anche una variabile.
Ruben Verborgh,

1
Beh, si assegna aad arguments[0]passando come parametro.
Ruben Verborgh,

1
@RubenVerborgh sì, ma non si crea il argumentse la sua assegnazione avviene "dietro le quinte"
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);

rimuovi o commenta i 2 // o ed esegui con un unico set di codice

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


2

Siamo in grado di scambiare var in questo modo:

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 ora c'è un compito di destrutturazione e puoi fare:

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

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

un approccio più dettagliato sarebbe

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


1

Fino a ES5, per scambiare due numeri, è necessario creare una variabile temp e quindi scambiarla. Ma in ES6, è molto facile scambiare due numeri usando la distruzione dell'array. Vedi esempio.

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

Perché sento che questo metodo funziona più lentamente:

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

Se hai intenzione di archiviare i tuoi var in un oggetto (o array), questa funzione dovrebbe funzionare:

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

Uso:

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

Possiamo usare IIFE per scambiare due valori senza parametro aggiuntivo

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

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


1

La destrutturazione dell'array ES6 viene utilizzata per scambiare due variabili. vedi esempio

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

Modo più semplice possibile con:

x === 1e y === 2; Ma dopo la destrutturazione, xè y, cioè 2, ed yè x, cioè 1.


1

Scambia usando Bitwise

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

Scambio a linea singola "utilizzando array"

[a, b] = [b, a]

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.