JavaScript에서 두 변수를 바꾸는 방법


답변:


321

다음은 두 변수의 값을 바꾸는 하나의 라이너입니다.
주어진 변수 ab:

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

아래 데모 :

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. 그러나 가장 짧은 버전은 ECMAScript 6 [a, b] = [b, a];입니다.
dfsq

8
@ Kay : 세 번째 변수 대신 배열을 사용하는 것이 훨씬 느린 것 같습니다 : http://jsperf.com/swap-array-vs-variable Chrome에서만 이것을 테스트했습니다. 현재 Invalid left-hand side in assignment 오류가 발생 하여 ECMAScript 6 버전을 테스트 할 수 없었습니다 .
Nope

2
@ FrançoisWahl 좋은 지적입니다. 나는 여기에있는 대부분의 답변이 효과가 있고 상당히 동등하다고 생각합니다. 임시 변수 사용, 코드 양 및 속도 간의 균형이 맞다고 가정합니다.
showdev

3
@ FrançoisWahl 잘, 나는이 솔루션이 너무 느리다고 추측하지 않았을 것입니다. 또한보십시오 : jsperf.com/swap-array-vs-variable/3
kay-SE is evil

3
@showdev Ted Hopp의 답변에서 Dijkstra 인용문을 읽으십시오.
Brian McCutchon

185

ES6 (Firefox 및 Chrome은 이미이를 지원합니다 (할당 배열 일치 구성)) :

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


2
누구든지 es6에서 그러한 종류의 스왑의 이름을 알고 있습니까?
derek

6
@derek-나는 그것을 소멸 할당 의 형태 인 배열 매칭 이라고 생각합니다 .
Ted Hopp

4
이것은 nodejs 7.4.0 / win7 64의 세 번째 변수 방법보다 약 35 배 느린 것으로 보입니다. 그러나 그것은 깔끔합니다.
mkey


5
V8 버전 6.8부터는 배열을 파괴하는 변수를 임시 변수 ( v8project.blogspot.com/2018/06/v8-release-68.html ) 만큼 빠르게 교체해야합니다 .
Ruben Verborgh

120

당신은 이것을 할 수 있습니다 :

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

가독성과 유지 관리 성을 위해 이것은 적어도 JavaScript에서는 이길 수 없습니다. 6 개월 후부터 코드를 유지 관리하는 사람이라면 무슨 일이 일어나고 있는지 정확히 알 수 있습니다.

이것들은 정수이므로, 많은 영리한 트릭 1 을 사용하여 세 번째 변수를 사용하지 않고 바꿀 수 있습니다. 예를 들어 비트 xor 연산자를 사용할 수 있습니다.

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

이것을 XOR 스왑 알고리즘이라고합니다. 운영 이론은 이 위키 백과 기사에 설명되어 있습니다.

1 "유능한 프로그래머는 자신의 두개골의 제한된 크기를 완전히 알고 있습니다. 따라서 그는 겸손하게 자신의 임무에 접근하여 전염병과 같은 영리한 속임수를 피합니다." — Edsger W. Dijkstra


Xor는 모든 데이터 유형에서 작동합니다. 숫자로만 작동하는 빼기 트릭입니다.
Rob Grant

11
@RobertGrant-JavaScript의 xor 연산자는 피연산자를 32 비트 정수로 변환합니다 ( ToInt32내부 방법을 사용 하여 ECMAScript 표준의 11.10 절 참조 ). 정수가 아닌 숫자 값에 대한 올바른 결과를 생성하지 않습니다. 또한 숫자가 아닌 값을 32 비트 정수로 변환합니다. 당신이 시작하는 경우 a = "hi"b = "there", 당신이와 끝까지 a == 0하고 b == 0.
Ted Hopp

1
이 트릭은 정수 결과를 신경 쓰지 않으면 모든 데이터 유형에서 작동합니다. 값은 int32로 자동 캐스트됩니다. 즉, 숫자 문자열, 부울 (0/1), null (0) 및 빈 배열 / 객체 (0)에 사용할 수 있습니다. 원래의 형태가 유지되지 않지만, 그래서 부울이 작동하지 않을 영향을 typeof a == 'boolean'하거나 a === false예를 들어,. 실수는 0에 가깝고 가장 가까운 정수로 반올림되는 것을 제외하고 작동합니다.
Beejor

1
@Beejor-즉, 정수 값이 아닌 경우를 제외하고 모든 데이터 유형에서 작동합니다. 필자의 책에서 "스왑"은 "int32로 변환 한 다음 스왑"하는 것이 아니라 "각 변수가 다른 값을 갖는 것으로 끝남"을 의미합니다.
Ted Hopp

@TedHopp 박람회. 나는 좋은 스왑 솔루션으로 작동하는 것이 아니라 데이터 유형을 던질 수 있다는 점에서 "작동"을 의미했습니다. 나는 그것이 일반적으로별로 유용하지 않다는 데 동의합니다.
Beejor

58

아래 코드를 사용하지 마십시오. 두 변수의 값을 바꾸는 것이 권장되는 방법 은 아닙니다 ( 일시적으로 임시 변수사용하십시오 ). JavaScript 트릭 만 보여줍니다.

이 솔루션은 임시 변수, 배열, 하나의 추가 만 사용하며 빠릅니다 . 사실, 때로는 여러 플랫폼에서 임시 변수보다 빠릅니다 .
그것은 모든 수에 적용되며 오버플로가 발생하지 않으며 Infinity 및 NaN과 같은 엣지 케이스를 처리합니다.

a = b + (b=a, 0)

두 단계로 작동합니다.

  • (b=a, 0)세트 b이전의 값 a과 수율0
  • a = b + 0세트 a의 이전 값b

5
temp var 버전은 약간 더 빠르며 더 일반적이며 더 읽기 쉽습니다. jsperf.com/swap-two-numbers-without-tmp-var/9
Antimony

이 () 구문은 무엇을 의미합니까? 어떻게 0을 산출합니까?
피트 알빈

8
괄호 안의 연산자는 쉼표 연산자 ,이며 우선 순위를 설정하기 위해 줄 바꿈되었습니다. 쉼표 연산자는 두 인수 (이 경우 b=a0)를 모두 평가 하고 마지막 (이 경우 0)을 반환합니다 . 따라서 여기서는 새로운 b값을 이전 값으로 설정 a하고을 산출 하는 효과가 0있습니다.
Ruben Verborgh

6
이것이 숫자 값에서만 작동한다고 생각합니까? var a = "hello"b = "world"를 a = "world0"과 같이 사용할 수 없습니다.
Chris GW Green

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

19

ES6부터는 변수를보다 우아하게 바꿀 수도 있습니다.

var a = 1,
    b = 2;

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

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

18

여기서 한 라이너 가정이다 ab이미 존재하고 교환 할 필요가 값을 가지고

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

@Kay가 언급했듯이 이것은 실제로 배열 방식보다 성능이 뛰어납니다 (거의 2 배 빠름).


1
이상적인 대답과 마찬가지로, 스왑 할 때 변수 a & b를 다시 선언하지 않고 명시적인 변수 이름 "tmp"를 사용하는 것이 좋습니다. 처럼 : var a, b, tmp; a = 1; b = 2; tmp=a, a=b, b=tmp; 개인적인 취향.
Johnny Wong

10

다음과 같이 세 번째 변수를 사용하십시오.

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

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

데모 -세 번째 변수 사용



10

ES6 + 방법 : ES6부터 변수를보다 우아하게 바꿀 수 있습니다. 할당 할당 배열 일치를 사용할 수 있습니다. 간단합니다. var a = 10 b = 20;

[a, b] = [b, a]

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


10

이제 마침내 할 수 있습니다 :

let a = 5;
let b = 10;

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

console.log(a, b);


9

임시 스왑 변수 또는 XOR을 사용할 수 있습니다.

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

이것은 기본적인 논리적 개념이며 XOR 작업을 지원하는 모든 언어에서 작동합니다.

편집 : 의견을 참조하십시오. 이것이 정수로만 작동한다는 것을 잊어 버렸습니다. 질문의 스레드에서 정수 변수를 가정


16
프로그래밍 인터뷰 및 기타 일반적인 사소한 사건에 사용됩니다. 그러나 이것은 실생활에서 가치를 교환하는 다소 어리석은 방법입니다. 우선 JS에서는 정수로만 작동합니다.
cHao

1
@Kay "지난 30 년 동안 진짜가 아니라"는 무슨 뜻입니까? 나는 의미가있을 때마다 비트 연산자를 사용합니다. 실제로는 꽤 자주 (예를 들어, 알 수없는 부울을 토글합니다)
Ben Harold

1
@cHao 비트 단위 연산자는 지속적으로 (그리고 지금까지) 내 컴퓨터에서 가장 빠른입니다 : jsperf.com/swap-array-vs-variable/2
벤 해롤드

3
@php_surgeon 컴파일러가 변수를 죽은 것으로 표시 할 수 없도록 바이올린을 약간 변경했습니다. jsperf.com/swap-array-vs-variable/3 . 임시 VAR 솔루션은 빠르게 XOR 스왑 솔루션보다 지금 1/4
케이 - SE는 악

1
@Kay 어떤 것이 안정적이고 잘 주석 처리되고 가장 빠른 기술이며 한두 곳에서만 사용되는 상황에서는 프로덕션 코드에서 왜 좋지 않은지 알 수 없습니다. 일반적으로 비트 단위 연산은 어려운 개념이므로 코드에서 이미 많은 것을 사용하는 경우 관리자는 어쨌든 익숙해야합니다. 대부분의 경우 분명히 과잉입니다. 나는 단지 담요 진술이 항상 도움이되는 것은 아니라고 생각한다. "goto"와 "eval"까지 모든 곳이 있습니다.
Beejor


7

귀하의 질문이 소중했던 것처럼 "이 변수들만이 아니라 다른 변수들"입니다.

var a = 1, b = 2

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

트릭입니다.

Rodrigo Assis가 말했듯이 "더 짧을 수 있습니다"

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

데모 : http://jsfiddle.net/abdennour/2jJQ2/


1
@DmiN의 답변과 같은 결함.
kay-SE는 악하다

어디에서 결함이 발견됩니까? 그것은 영광
스럽지

2
@AbdennourToumi Kay는 귀하의 답변이 정수로만 작동한다는 사실을 언급한다고 생각합니다.
showdev

1
@showdev : 다시 읽어주십시오. question : "이 변수들만이 아니라 어떤 객체도 아닙니다".... 내 대답은 의문으로 소중합니다. 나는 당신에게 의견을 표시하도록 요청한다. 나는 반복한다 : 그것은 영광스럽지 않다.
Abdennour TOUMI

1
이 대화는 기괴합니다. @AbdennourTOUMI-변수는 정수와 다릅니다. 객체, 문자열, 함수, null 등을 가리키는 변수를 가질 수 있습니다.
Rob Grant

6

ES6 파괴 :

배열 사용하기 : [a, b] = [b, a]; // my favorite

객체 사용하기 : {a, b} = {a:b, b:a}; // not bad neither


4

우리는 어떻게이 고전적인 oneliners를 놓칠 수 있을까

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

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

마지막은 전역 변수 '_'를 노출하지만 일반적인 자바 스크립트 규칙은이 변수를 '무관심'변수로 사용하는 것이 중요하지 않습니다.


1
두 번째에는 오타가 있습니다. 그것은해야한다a = (_=b,b=a,_);
Mageek

밑줄 _은 무엇을 의미합니까? 왜 선언이 필요하지 않습니까?

밑줄은 단지 전역 변수 이름이므로 유효한 이름으로 바꿀 수 있습니다. 예 : a = (justsomething = b, b = a, justsomething)
Teemu Ikonen

6
아뇨, 선언되지 않은 매직-글로벌 변수를 사용하지 마십시오! 그것은 실제 생활에서 끔찍한 버그에 대한 확실한 방법입니다.
oriadam

underscore.js를 사용하는 사람 은 두 번째 것을 시도하면 매우 불행 할 것입니다.
Ted Hopp

3

나는 일종의 프로그래밍 올림피아드를 본다. 하나 더 까다로운 단선 솔루션 :

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

피들 : http://jsfiddle.net/cherniv/4q226/


2
필요가 느린을 사용 없습니다 arguments만 수행합니다 b = (function (x){ return x; })(a, a=b).
Ruben Verborgh

1
@RubenVerborgh 네, 그러나 인수를 사용하면 세 번째 변수를 정의하지 않습니다!
Cherniv

1
기술적으로 arguments목록도 변수가됩니다.
Ruben Verborgh '12

1
글쎄, 당신은 그것을 매개 변수로 전달하여 할당 a합니다 arguments[0].
Ruben Verborgh

1
@RubenVerborgh yes,하지만 당신은 만들지 않습니다 arguments 할당은 "장면 뒤에서"
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);

2를 제거하거나 주석을 달고 한 세트의 코드로 실행하십시오.

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


2

var를 다음과 같이 바꿀 수 있습니다.

var val1 =  117,
    val2 = 327;

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


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

더 장황한 접근 방식은

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


1

ES5까지 두 숫자를 바꾸려면 임시 변수를 만든 다음 바꿔야합니다. 그러나 ES6에서는 배열 소멸을 사용하여 두 숫자를 쉽게 바꿀 수 있습니다. 예를 참조하십시오.

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

이 방법이 느리게 실행된다고 들었습니다.

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

var를 객체 (또는 배열)에 저장하려는 경우이 기능이 작동합니다.

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

용법:

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

IIFE를 사용하여 추가 매개 변수없이 두 값을 교환 할 수 있습니다

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

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


1

ES6 배열 파괴는 두 변수를 교환하는 데 사용됩니다. 예를 참조하십시오

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

보다 쉬운 방법 :

x === 1그리고 y === 2; 그러나 destructuring 후, x이다 y2,하고 y있습니다 x1.


1

비트 단위를 사용하여 스왑

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

단일 어레이 스왑 "어레이 사용"

[a, b] = [b, a]

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.