Cómo intercambiar dos variables en JavaScript

Respuestas:

321

Aquí hay una línea para intercambiar los valores de dos variables.
Variables dadas ay b:

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

Demostración a continuación:

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>

showdev
fuente
264
+1. Pero la versión más corta será en ECMAScript 6: [a, b] = [b, a];.
dfsq
8
@Kay: También parece ser mucho más lento usar una matriz en lugar de una tercera variable: http://jsperf.com/swap-array-vs-variable . Sin embargo, solo probé esto en Chrome. Todavía no pude probar la versión ECMAScript 6, ya que actualmente da un Invalid left-hand side in assignment error.
No,
2
@ FrançoisWahl Buen punto. Creo que la mayoría de las respuestas aquí funcionarán y son bastante equivalentes. Supongo que es una compensación entre el uso variable temporal, la cantidad de código y la velocidad.
showdev
3
@ FrançoisWahl bueno, no habría adivinado que esta solución era mucho más lenta. Ver también: jsperf.com/swap-array-vs-variable/3
kay - SE is evil
3
@showdev Lea la cita de Dijkstra en la respuesta de Ted Hopp.
Brian McCutchon
185

ES6 (Firefox y Chrome ya lo admiten (Destructuring Assignment Array Matching)):

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

Pedro Justo
fuente
2
Alguien sabe el nombre de este tipo de intercambio en ES6?
derek
66
@derek: creo que se llama coincidencia de matrices , una forma de asignación de desestructuración .
Ted Hopp
44
Esto parece ser aproximadamente 35 veces más lento que el tercer método variable en nodejs 7.4.0 / win7 64. Pero es claro.
mkey
55
Desde la versión 6.8 de V8, el intercambio de variables con la desestructuración de matrices debe ser tan rápido como con una variable temporal ( v8project.blogspot.com/2018/06/v8-release-68.html ).
Ruben Verborgh
120

Puedes hacerlo:

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

Para facilitar la lectura y la mantenibilidad, esto no puede ser mejor (al menos en JavaScript). Cualquiera que mantenga el código (incluido usted dentro de seis meses) sabrá exactamente lo que está sucediendo.

Dado que estos son enteros, también puede usar cualquier número de trucos inteligentes 1 para intercambiar sin usar una tercera variable. Por ejemplo, puede usar el operador 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);

Esto se llama algoritmo de intercambio XOR. Su teoría de funcionamiento se describe en este artículo de Wikipedia .

1 "El programador competente es plenamente consciente del tamaño limitado de su propio cráneo. Por lo tanto, aborda su tarea con total humildad y evita trucos ingeniosos como la peste". - Edsger W. Dijkstra

Ted Hopp
fuente
Xor funcionará con cualquier tipo de datos. Es el truco de resta que solo funcionará con números.
Rob Grant
11
@RobertGrant: el operador xor en JavaScript convierte sus operandos a enteros de 32 bits (utilizando el ToInt32método interno; consulte la Sección 11.10 del estándar ECMAScript ). No produce los resultados correctos para valores numéricos no enteros. También convierte valores no numéricos en enteros de 32 bits. Si comienzas con a = "hi"y b = "there", terminas con a == 0y b == 0.
Ted Hopp
1
Este truco funciona con cualquier tipo de datos, siempre que no te importe un resultado entero; los valores se convierten automáticamente en int32s. Esto significa que puede funcionar con cadenas numéricas, booleanos (0/1), nulos (0) y matrices / objetos vacíos (0). Aunque el tipo de original no se conserva, por lo afectados Booleanos no quiere trabajar con typeof a == 'boolean'o a === false, por ejemplo. Los números reales funcionan, excepto que se mueven hacia cero frente a redondeados al entero más cercano.
Beejor
1
@Beejor: en otras palabras, funciona con cualquier tipo de datos, excepto que no lo hace (a menos que sean valores enteros). En mi libro, "swap" significa "terminar con cada variable teniendo el valor que tenía la otra", no "convertir a int32 y luego intercambiar".
Ted Hopp
@TedHopp Bastante justo. Quise decir "funciona" en términos del hecho de que puede arrojar cualquier tipo de datos, no porque funcione como una buena solución de intercambio. Estoy de acuerdo que no es muy útil en general.
Beejor
58

No use el código a continuación. Es no la forma recomendada para intercambiar los valores de dos variables (simplemente utilizar una variable temporal para eso). Simplemente muestra un truco de JavaScript.

Esta solución no utiliza variables temporales, ni matrices, solo una adición, y es rápida . De hecho, a veces es más rápido que una variable temporal en varias plataformas .
Funciona para todos los números, nunca se desborda y maneja casos extremos como Infinity y NaN.

a = b + (b=a, 0)

Funciona en dos pasos:

  • (b=a, 0)establece bel valor anterior de ay rinde0
  • a = b + 0establece ael valor anterior deb
Ruben Verborgh
fuente
55
La versión var temporal es un poco más rápida, y más general y más legible también. jsperf.com/swap-two-numbers-without-tmp-var/9
Antimony
¿Qué significa esta sintaxis ()? ¿Cómo produce 0?
Pete Alvin
8
El operador entre paréntesis es el operador de coma ,, y se ha ajustado para establecer la prioridad correcta. El operador de coma evalúa sus dos argumentos (en este caso b=ay 0) y devuelve el último (en este caso 0). Entonces, aquí tiene el efecto de establecer lo nuevo ben el valor anterior de a, al tiempo que cede 0.
Ruben Verborgh
66
¿Estoy en lo cierto al pensar que esto solo funciona para el valor numérico? No puede usar esto con, por ejemplo, var a = "hola" b = "mundo" como a = "mundo0".
Chris GW Green
3
@ChrisGWGreen:a = b + (b=a, "")
19

Desde ES6, también puede intercambiar variables de manera más elegante:

var a = 1,
    b = 2;

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

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

Aquí hay una sola línea, asumiendo ay bya existen y tienen valores que necesitan ser intercambiado:

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

Como @Kay mencionó, esto realmente funciona mejor que la forma de matriz (casi 2 veces más rápido).

bobobobo
fuente
1
Al igual que mi respuesta ideal, simplemente prefiero no volver a declarar la variable a & b al intercambiar, y usar el nombre explícito de variable "tmp". Al igual que: var a, b, tmp; a = 1; b = 2; tmp=a, a=b, b=tmp; Gusto personal.
Johnny Wong
10

Use una tercera variable como esta:

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

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

DEMO - Usando una tercera variable


No
fuente
10

Método ES6 +: desde ES6, puede intercambiar variables de manera más elegante. Puede usar la desestructuración de la asignación de matriz de asignación. Es simplemente. var a = 10 b = 20;

[a, b] = [b, a]

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

Jalak Patoliya
fuente
10

Ahora puedes finalmente hacer:

let a = 5;
let b = 10;

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

console.log(a, b);

mehulmpt
fuente
9

Puede usar una variable de intercambio temporal o XOR.

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

Este es solo un concepto lógico básico y funciona en todos los idiomas que admiten la operación XOR.

editar: ver los comentarios. Olvidé decir que esto funciona con seguridad solo con un entero. Asumimos las variables enteras del hilo de la pregunta

DmiN
fuente
16
Trabaja para programar entrevistas y otros casos generales de trivia. Sin embargo, tenga en cuenta que esta es una forma bastante estúpida de intercambiar valores en la vida real. Por un lado, en JS, solo funciona con enteros.
cHao
1
@Kay ¿Qué quieres decir con "no ha sido real en los últimos 30 años?" Utilizo operadores bit a bit siempre que tenga sentido, lo que en realidad es bastante frecuente (alternar un booleano desconocido, por ejemplo)
Ben Harold
1
El operador @cHao Bitwise es constantemente (y con diferencia) el más rápido en mi máquina: jsperf.com/swap-array-vs-variable/2
Ben Harold
3
@php_surgeon Cambié un poco el violín para que el compilador no pueda marcar las variables como muertas. jsperf.com/swap-array-vs-variable/3 . La solución var temporal es ahora 1/4 más rápida que la solución de intercambio xor
kay - SE es malvada
1
@Kay En situaciones en las que algo es estable, está bien comentado, es la técnica más rápida y se usa solo en uno o dos lugares, no veo por qué no estaría bien en el código de producción. Las operaciones bit a bit en general son un concepto difícil, por lo que si el código ya usa un montón de ellas, los mantenedores necesitarían estar familiarizados con ellas de todos modos. Para la mayoría de los casos, obviamente es exagerado. Solo creo que las declaraciones generales no siempre son útiles; todo tiene un lugar, incluso "goto" y "eval".
Beejor
7

Como su pregunta era preciosa "Solo estas variables, no ningún objeto", la respuesta también será preciosa:

var a = 1, b = 2

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

es un truco

Y como dijo Rodrigo Assis, "puede ser más corto"

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

Demostración: http://jsfiddle.net/abdennour/2jJQ2/

Abdennour TOUMI
fuente
1
Las mismas fallas que la respuesta de @ DmiN.
kay - SE es malvado
donde encuentras fallas? No es honorable
Abdennour TOUMI
2
@AbdennourToumi Creo que Kay se refiere al hecho de que su respuesta solo funciona con números enteros.
showdev
1
@showdev: Lea nuevamente la pregunta: "Solo estas variables, no ningún objeto" ... mi respuesta es preciosa como pregunta. Le pido que marque el comentario. Repito: no es honorable.
Abdennour TOUMI
1
Esta conversación es extraña. @AbdennourTOUMI: las variables no son lo mismo que los enteros. Puede tener variables que apuntan a objetos, cadenas, funciones, nulos, etc.
Rob Grant
6

Desestructuración de ES6:

Usando una matriz: [a, b] = [b, a]; // my favorite

Usando un objeto: {a, b} = {a:b, b:a}; // not bad neither

Flavien Volken
fuente
4

¿Cómo podríamos perder estos clásicos de línea?

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

Y

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

La última expone la variable global '_', pero eso no debería importar, ya que la convención típica de JavaScript es usarla como variable 'no importa'.

Teemu Ikonen
fuente
1
Hay un error tipográfico en el segundo. Debería sera = (_=b,b=a,_);
Mageek
¿Qué significa el guión bajo _? ¿Por qué no necesita declaración?
día
el subrayado es solo un nombre de variable global, puede reemplazarlo por uno válido. por ejemplo, a = (justusomething = b, b = a, justusomething)
Teemu Ikonen
66
¡Oh no, no uses vars mágicos globales no declarados! Esa es una forma segura de errores horribles en la vida real.
oriadam
Cualquiera que use underscore.js se sentirá muy descontento si prueba el segundo.
Ted Hopp
3

Veo una especie de olimpiada de programación aquí. Una solución más complicada de una línea:

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

Violín: http://jsfiddle.net/cherniv/4q226/

Cherniv
fuente
2
No es necesario usar el lento arguments, solo hazlo b = (function (x){ return x; })(a, a=b).
Ruben Verborgh
1
@RubenVerborgh sí, pero con argumentos no estamos definiendo una tercera variable.
Cherniv
1
Técnicamente, la argumentslista también sería una variable.
Ruben Verborgh
1
Así, se asigna aa arguments[0]pasándolo como parámetro.
Ruben Verborgh
1
@RubenVerborgh sí, pero no crea argumentsy su asignación ocurre "detrás de escena"
Cherniv
3

Intercambio de una línea

a = a^b^(b^=(a^b));
Saruselvi
fuente
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);

eliminar o comentar los 2 // o y ejecutar con un conjunto de código

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

Thilak Raj
fuente
2

Podemos intercambiar var así:

var val1 =  117,
    val2 = 327;

val2 = val1-val2; 
console.log(val2);
val1 = val1-val2;
console.log(val1);
val2 = val1+val2;
console.log(val2);
Mohammed Javed
fuente
2

En ES6 ahora hay una tarea de desestructuración y puedes hacer:

let a = 1;
let b = 2;
[b, a] = [a, b]  // a = 2, b = 1
Stanislav Bozhanov
fuente
1
let a = 2, b = 4;
[b, a] = [a, b];

un enfoque más detallado sería

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

Hasta ES5, para intercambiar dos números, debe crear una variable temporal y luego intercambiarla. Pero en ES6, es muy fácil intercambiar dos números usando la desestructuración de matrices. Ver ejemplo.

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
Avinash Malhotra
fuente
1

Porque escuché que este método funciona más lento:

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

Si planea almacenar sus variables en un objeto (o matriz), esta función debería funcionar:

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'}
SwiftNinjaPro
fuente
1

Podemos usar el IIFE para intercambiar dos valores sin parámetro adicional

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

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

Ganesh Phirke
fuente
1

La desestructuración de la matriz ES6 se utiliza para intercambiar dos variables. Ver ejemplo

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

La forma más fácil posible con:

x === 1y y === 2; Pero después de la desestructuración, xes , es ydecir 2, y yes x, es decir 1.

Krish Malhotra
fuente
1

Cambiar usando Bitwise

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

Intercambio de una sola línea "con matriz"

[a, b] = [b, a]
HusseiELbadady
fuente
-5

(función (A, B) {b = A; a = B;}) (parseInt (a), parseInt (b));

Carlos Correia
fuente