Como trocar duas variáveis ​​em JavaScript

Respostas:

321

Aqui está uma lista para trocar os valores de duas variáveis.
Dadas variáveis ae b:

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

Demonstração abaixo:

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
fonte
264
+1. Mas a versão mais curta será no ECMAScript 6: [a, b] = [b, a];.
dfsq
8
@ Kay: Também parece ser muito mais lento usando uma matriz em vez de uma terceira variável: http://jsperf.com/swap-array-vs-variable Eu só testei isso no Chrome. Ainda não pude testar a versão do ECMAScript 6, pois atualmente há um Invalid left-hand side in assignment erro.
Não,
2
@ FrançoisWahl Bom ponto. Eu acho que a maioria das respostas aqui funcionará e é bastante equivalente. Suponho que seja uma troca entre uso temporário de variável, quantidade de código e velocidade.
showdev
3
@ FrançoisWahl bem, eu não imaginaria que essa solução fosse muito mais lenta. Veja também: jsperf.com/swap-array-vs-variable/3
kay - SE is evil
3
@showdev Leia a citação de Dijkstra na resposta de Ted Hopp.
Brian McCutchon
185

ES6 (o Firefox e o Chrome já o suportam (correspondência de matriz de atribuição de reestruturação)):

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

Pedro Justo
fonte
2
alguém sabe o nome desse tipo de troca no es6?
Derek
6
@ Derek - Eu acho que é chamado de correspondência de matriz , uma forma de atribuição de desestruturação .
Ted Hopp
4
Parece ser cerca de 35 vezes mais lento que o terceiro método variável no nodejs 7.4.0 / win7 64. Mas com certeza é legal.
Mck
5
Desde a versão 6.8 da V8, a troca de variáveis ​​pela desestruturação da matriz deve ser tão rápida quanto a uma variável temporária ( v8project.blogspot.com/2018/06/v8-release-68.html ).
precisa saber é o seguinte
120

Você consegue fazer isso:

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

Para facilitar a leitura e a manutenção, isso não pode ser melhorado (pelo menos em JavaScript). Qualquer pessoa que mantenha o código (incluindo você daqui a seis meses) saberá exatamente o que está acontecendo.

Como esses números são inteiros, você também pode usar qualquer número de truques inteligentes 1 para trocar sem usar uma terceira variável. Por exemplo, você pode usar o 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);

Isso é chamado de algoritmo de troca XOR. Sua teoria da operação é descrita neste artigo da Wikipedia .

1 "O programador competente está plenamente consciente do tamanho limitado de seu próprio crânio. Portanto, ele aborda sua tarefa com total humildade e evita truques inteligentes como a praga". - Edsger W. Dijkstra

Ted Hopp
fonte
O Xor funcionará com qualquer tipo de dados. É o truque de subtração que só funciona com números.
Rob Grant
11
@RobertGrant - O operador xor em JavaScript converte seus operandos em números inteiros de 32 bits (usando o ToInt32método interno - consulte a Seção 11.10 do padrão ECMAScript ). Não produz os resultados corretos para valores numéricos não inteiros. Também converte valores não numéricos em números inteiros de 32 bits. Se você começa com a = "hi"e b = "there", acaba com a == 0e b == 0.
precisa saber é o seguinte
1
Esse truque funciona com qualquer tipo de dado, desde que você não se importe com um resultado inteiro; os valores são convertidos automaticamente para int32s. Isso significa que ele pode trabalhar com seqüências numéricas, booleanos (0/1), nulos (0) e matrizes / objetos vazios (0). Embora o tipo original não seja preservado, os booleanos afetados não funcionam com typeof a == 'boolean'ou a === false, por exemplo. Os números reais funcionam, exceto que são calculados com base no zero e arredondados para o número inteiro mais próximo.
Beejor 21/09/16
1
@ Beejor - Em outras palavras, ele funciona com qualquer tipo de dados, exceto que não (a menos que sejam valores inteiros). No meu livro, "swap" significa "terminar com cada variável tendo o valor que a outra tinha", não "converter para int32 e depois trocar".
Ted Hopp
@TedHopp Fair o suficiente. Eu quis dizer "funciona" em termos do fato de que você pode jogar qualquer tipo de dado, não como funciona como uma boa solução de troca. Concordo que não é muito útil em geral.
Beejor 27/09/16
58

Não use o código abaixo. É não a maneira recomendada para trocar os valores das duas variáveis (simplesmente usar uma variável temporária para isso). Apenas mostra um truque de JavaScript.

Esta solução não usa variáveis ​​temporárias, matrizes, apenas uma adição e é rápida . De fato, às vezes é mais rápido que uma variável temporária em várias plataformas .
Ele funciona para todos os números, nunca transborda e lida com casos extremos, como Infinity e NaN.

a = b + (b=a, 0)

Funciona em duas etapas:

  • (b=a, 0)define bo valor antigo de ae produz0
  • a = b + 0define ao valor antigo deb
Ruben Verborgh
fonte
5
A versão temp var é um pouco mais rápida, mais geral e mais legível também. jsperf.com/swap-two-numbers-without-tmp-var/9
Antimony
O que essa sintaxe () significa? como isso gera 0?
Pete Alvin
8
O operador entre parênteses é o operador de vírgula ,e foi moldado para definir a precedência corretamente. O operador de vírgula avalia os dois argumentos (neste caso b=ae 0) e retorna o último (neste caso 0). Portanto, aqui, ele tem o efeito de definir o novo bpara o valor antigo de a, enquanto produz 0.
Ruben Verborgh
6
Estou certo ao pensar que isso só funciona com valor numérico? Você não pode usar isso com, por exemplo, var a = "olá" b = "world" como a = "world0".
Chris GW Verde
3
@ChrisGWGreen:a = b + (b=a, "")
19

Desde o ES6, você também pode trocar variáveis ​​de maneira mais elegante:

var a = 1,
    b = 2;

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

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

Aqui está uma linha, assumindo ae bjá existindo e com valores que precisam ser trocados:

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

Como o @Kay mencionou, isso realmente tem um desempenho melhor que o do array (quase duas vezes mais rápido).

bobobobo
fonte
1
Como minha resposta ideal, só prefiro não declarar a variável a & b ao trocar e usar o nome explícito da variável "tmp". Curtir var a, b, tmp; a = 1:; b = 2; tmp=a, a=b, b=tmp; Gosto pessoal.
Johnny Wong
10

Use uma terceira variável 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 uma terceira variável


Não
fonte
10

Método ES6 +: desde o ES6, você pode trocar variáveis ​​de maneira mais elegante. Você pode usar a correspondência de matriz de atribuição de desestruturação. É simplesmente. var a = 10 b = 20;

[a, b] = [b, a]

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

Jalak Patoliya
fonte
10

Agora você pode finalmente fazer:

let a = 5;
let b = 10;

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

console.log(a, b);

mehulmpt
fonte
9

Você pode usar uma variável de troca temporária ou XOR.

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

Este é apenas um conceito lógico básico e funciona em todos os idiomas que suportam a operação XOR.

editar: veja os comentários. Esqueci de dizer que isso funciona com certeza apenas com número inteiro. Assumiu as variáveis ​​inteiras do encadeamento da pergunta

DmiN
fonte
16
Trabalha para programar entrevistas e outros casos gerais de trivialidades. Observe, porém, que essa é uma maneira bastante estúpida de trocar valores na vida real. Por um lado, em JS, ele funciona apenas com números inteiros.
precisa saber é
1
@Kay O que você quer dizer com "não é uma coisa real nos últimos 30 anos?" Eu uso operadores bit a bit sempre que fizer sentido, que é realmente muito frequentemente (alternando um boolean desconhecido, por exemplo)
Ben Harold
1
operador @cHao Bitwise é consistentemente (e de longe) o mais rápido na minha máquina: jsperf.com/swap-array-vs-variable/2
Ben Harold
3
@php_surgeon Mudei um pouco o violino para que o compilador não possa marcar as variáveis ​​como inoperantes. jsperf.com/swap-array-vs-variable/3 . A solução temporária var agora é 1/4 mais rápido do que a solução xor troca
kay - SE é mau
1
@Kay Em situações em que algo é estável, bem comentado, a técnica mais rápida e usada em apenas um ou dois lugares, não vejo por que não seria bom no código de produção. As operações bit a bit em geral são um conceito difícil; portanto, se o código já usa várias delas, os mantenedores precisariam estar familiarizados com elas de qualquer maneira. Na maioria dos casos, é obviamente um exagero. Apenas acho que declarações gerais nem sempre são úteis; tudo tem um lugar, até "ir" e "eval".
Beejor 21/09/16
7

Como sua pergunta era preciosa "Somente essas variáveis, não objetos", a resposta também será preciosa:

var a = 1, b = 2

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

é um truque

E como Rodrigo Assis disse, "pode ​​ser mais curto"

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

Demonstração: http://jsfiddle.net/abdennour/2jJQ2/

Abdennour TOUMI
fonte
1
Mesmas falhas da resposta do @ DmiN.
kay - SE is evil
onde você encontra falhas? Não é honroso
Abdennour TOUMI
2
@AbdennourToumi Acho que Kay está se referindo ao fato de que sua resposta só funciona com números inteiros.
showdev
1
@showdev: Por favor, leia novamente a pergunta: "Somente essas variáveis, não quaisquer objetos" .... minha resposta é preciosa como pergunta. Peço que você sinalize o comentário. Repito: não é honroso.
Abdennour TOUMI
1
Essa conversa é bizarra. @AbdennourTOUMI - variáveis ​​não são iguais a números inteiros. Você pode ter variáveis ​​que apontam para objetos, seqüências de caracteres, funções, nulas etc.
Rob Grant
6

ES6 Reestruturação:

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

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

Flavien Volken
fonte
4

Como poderíamos sentir falta desses oneliners clássicos

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

E

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

O último expõe a variável global '_', mas isso não deve importar como convenção javascript típica é usá-lo como variável 'não se importe'.

Teemu Ikonen
fonte
1
Há um erro de digitação no segundo. Deveria sera = (_=b,b=a,_);
Mageek
O que significa o sublinhado _? Por que não precisa de declaração?
dia
sublinhado é apenas o nome da variável global, você pode substituí-lo por qualquer válido. por exemplo, a = (justsomething = b, b = um, justsomething)
Teemu Ikonen
6
Oh não, não use vars mágicos-globais não declarados! Essa é uma maneira certa de erros horríveis na vida real.
oriadam
Qualquer pessoa que use underscore.js ficará muito infeliz se tentar o segundo.
Ted Hopp
3

Eu vejo o tipo de programação olímpica aqui. Mais uma solução complicada de uma linha:

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

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

Cherniv
fonte
2
Não há necessidade de usar o lento arguments, basta fazer b = (function (x){ return x; })(a, a=b).
Ruben Verborgh
1
@RubenVerborgh sim, mas com argumentos não estamos definindo uma terceira variável!
Cherniv
1
Tecnicamente, a argumentslista também seria uma variável.
Ruben Verborgh
1
Bem, você atribui aa arguments[0]isso passando-o como um parâmetro.
Ruben Verborgh
1
@RubenVerborgh sim, mas você não cria o argumentse a sua atribuição acontece "nos bastidores"
Cherniv
3

Troca de linha única

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

remova ou comente os 2 // ou's e execute com o conjunto de códigos

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

Thilak Raj
fonte
2

Podemos trocar var assim:

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
fonte
2

Agora, no ES6, existe uma atribuição de desestruturação e você pode:

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

uma abordagem mais detalhada seria

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

Até o ES5, para trocar dois números, você deve criar uma variável temporária e depois trocá-la. Mas no ES6, é muito fácil trocar dois números usando a desestruturação da matriz. Consultar exemplo.

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
fonte
1

Porque eu ouvi dizer que esse método é mais lento:

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

Se você planeja armazenar seus vars em um objeto (ou matriz), esta função deve 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
fonte
1

Podemos usar o IIFE para trocar dois valores sem parâmetro extra

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

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

ganesh phirke
fonte
1

A desestruturação do array ES6 é usada para trocar duas variáveis. consultar exemplo

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

Maneira mais fácil possível com:

x === 1e y === 2; Mas após a desestruturação, xé y, ie 2, e yé x, ie 1.

Krish Malhotra
fonte
1

Troque usando o Bitwise

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

Troca de linha única "usando matriz"

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

(função (A, B) {b = A; a = B;}) (parseInt (a), parseInt (b));

Carlos Correia
fonte