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>


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


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


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

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

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


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



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


10

Agora você pode finalmente fazer:

let a = 5;
let b = 10;

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

console.log(a, b);


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


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/


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


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'.


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/


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
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/


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

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

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


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

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'}

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


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.


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]

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.