JavaScriptで2つの変数を交換する方法


回答:


321

これは、2つの変数の値を交換するためのワンライナーです。
与えられた変数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 2013

8
@Kay:それもはるかに遅い代わりに、3番目の変数の配列を使用しているようだ:http://jsperf.com/swap-array-vs-variable私はかかわらず、Chromeでこれをテストしました。現在Invalid left-hand side in assignment エラーが発生しているため、ECMAScript 6のバージョンはまだテストできませんでした。
いいえ、2013

2
@FrançoisWahl良い点。ここでの答えのほとんどはうまくいくと思いますし、かなり同等です。一時的な変数の使用、コードの量、速度の間のトレードオフだと思います。
showdev 2013

3
@FrançoisWahlまあ、私はこのソリューションがとても遅いとは思っていませんでした。次も参照してください:jsperf.com/swap-array-vs-variable/3
は悪です

3
@showdevテッド・ホップの回答にあるダイクストラの引用を読んでください。
Brian McCutchon、2016年

185

ES6(FirefoxおよびChromeは既にサポートしています(Destructuring Assignment Array Matching)):

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の3番目の変数メソッドよりも約35倍遅いようです。しかし、それはきちんとしています。
mkey 2017


5
V8バージョン6.8以降、配列の構造化による変数の交換は、一時変数(v8project.blogspot.com/2018/06/v8-release-68.html)と同じくらい高速になるはずです。
ルーベンフェルボルフ2018

120

あなたはこれを行うことができます:

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

可読性と保守性のために、これは(少なくともJavaScriptでは)打ち負かすことはできません。コードを保守している人(6か月後を含む)は、何が起こっているのかを正確に把握できます。

これらは整数であるため、3番目の変数を使用せずに、任意の数の巧妙なトリック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 == 0b == 0
Ted Hopp、2015年

1
このトリックは、整数の結果を気にしない限り、どのデータ型でも機能します。値はint32sに自動キャストされます。これは、数値文字列、ブール(0/1)、null(0)、空の配列/オブジェクト(0)で機能することを意味します。元のタイプは保持されませんが、影響を受けるブール値は、たとえば、typeof a == 'boolean'またはa === falseで機能しません。実数は機能しますが、最も近い整数に丸められるのではなく、ゼロに向かってフロアされます。
Beejor 2016

1
@Beejor-言い換えれば、それが機能しない場合を除いて、任意のデータ型で機能します(整数値でない場合)。私の本では、「スワップ」は「int32に変換してからスワップする」ではなく、「各変数が他の変数が持っていた値で終了する」ことを意味します。
テッドホップ2016

@TedHoppフェア十分。私はあなたがそれでどんなデータ型でも投げることができるという点で「うまくいく」ことを意味しました、それが良いスワップ解決策として働くのではありません。一般的にはあまり役に立たないことに同意します。
Beejor 2016

58

以下のコードは使用しないでください。それはない(単に二つの変数の値を交換するために推奨される方法の一時的な変数を使用そのために)。JavaScriptのトリックを示しているだけです。

このソリューションは、一時変数、配列、追加を1つだけ使用せず、高速です。実際、いくつかのプラットフォームでは、一時変数よりも高速な場合あります
すべての数値で機能し、オーバーフローすることはなく、InfinityやNaNなどのエッジケースを処理します。

a = b + (b=a, 0)

これは2つのステップで機能します。

  • (b=a, 0)bの古い値に設定し、ayields0
  • a = b + 0a古い値に設定しますb

5
temp varバージョンは少し高速で、より一般的で読みやすくなっています。jsperf.com/swap-two-numbers-without-tmp-var/9
Antimony

この()構文はどういう意味ですか?どうやって0を生み出すのですか?
ピートアルビン

8
括弧内の演算子はコンマ演算子,であり、優先順位を設定するためにラップされています。コンマ演算子は、両方の引数(この場合はb=a0)を評価し、最後の引数(この場合は)を返します0。したがって、ここでba、を生成しながら、new をの古い値に設定する効果があります0
Ruben Verborgh 14年

6
これは数値に対してのみ機能すると思いますか?たとえば、var a = "hello" b = "world"をa = "world0"として使用することはできません。
クリスGWグリーン14

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; 個人的な好み。
ジョニーウォン2015年

10

次のような3番目の変数を使用します。

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

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

デモ-3番目の変数の使用



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
プログラミングのインタビューやその他の一般的な雑学の場合に役立ちます。ただし、これは実際の値を交換するためのかなり愚かな方法です。1つには、JSでは整数でのみ機能します。
cHao 2013

1
@ケイ「過去30年間、本物ではない」とはどういう意味ですか?意味があるときはいつでも、ビットワイズ演算子を使用します。これは実際にはかなり頻繁に行われます(たとえば、不明なブール値を切り替える)
Ben Harold

1
@cHao Bitwiseオペレーターは、私のマシンで一貫して(そしてはるかに)最速です:jsperf.com/swap-array-vs-variable/2
Ben Harold

3
@php_surgeonフィドルを少し変更して、コンパイラーが変数をデッドとしてマークできないようにしました。jsperf.com/swap-array-vs-variable/3。一時VARソリューションは、より速く、XORスワップソリューションよりも今の1/4である
ケイ- SEは悪である

1
@Kay何かが安定していて、コメントが豊富で、最速のテクニックであり、1つか2つの場所でしか使用されていない状況では、プロダクションコードではうまくいかない理由がわかりません。一般的にビット単位の操作は難しい概念であるため、コードがすでにそれらの多くを使用している場合、いずれにしてもメンテナーはそれらに慣れる必要があります。ほとんどの場合、それは明らかにやり過ぎです。私はただ、包括的陳述が常に役立つとは限らないと思います。「goto」や「eval」など、すべてに場所があります。
Beejor 2016


7

あなたの質問は「この変数のみで、オブジェクトではない」という貴重なものだったので、答えも貴重です。

変数a = 1、b = 2

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

それはトリックであり、

そしてロドリゴ・アシスが言ったように、それは「短くなることができる」

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

デモ:http : //jsfiddle.net/abdennour/2jJQ2/


1
@DmiNの回答と同じ障害。
わかった-SEは悪

あなたはどこで欠点を見つけますか?それは名誉ではありません
Abdennour TOUMI 2013

2
@AbdennourToumiケイはあなたの答えが整数でのみ機能するという事実を言及していると思います。
showdev 2013

1
@showdev:もう一度お読みください質問:「この変数のみで、オブジェクトはありません」...私の質問は貴重です。コメントにフラグを付けるようにお願いします。繰り返します:それは名誉ではありません。
Abdennour TOUMI 2013

1
この会話は奇妙です。@AbdennourTOUMI-変数は整数と同じではありません。オブジェクト、文字列、関数、nullなどを指す変数を持つことができます
Rob Grant


4

これらの古典的なワンライナーをどうやって見逃すことができますか

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

そして

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

最後の1つはグローバル変数「_」を公開しますが、一般的なJavaScriptの慣例では、それを「ドントケア」変数として使用するため、問題にはなりません。


1
2つ目のタイプミスがあります。それはする必要がありますa = (_=b,b=a,_);
マギーク

下線は_どういう意味ですか?なぜ宣言が必要ないのですか?

下線はグローバル変数名です。有効な名前に置き換えることができます。例a =(justsomething = b、b = a、justsomething)
Teemu Ikonen 14

6
ああ、宣言されていないマジックグローバル変数は使用しないでください!これは、現実の恐ろしいバグへの確実な方法です。
oriadam

underscore.jsを使用している人は、2つ目を試してみると非常に不幸になります。
Ted Hopp

3

私はここに一種のプログラミングオリンピックを見る。もう1つのトリッキーな1行のソリューション:

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 2013

1
@RubenVerborghはい、しかし引数では3番目の変数を定義していません!
Cherniv 2013

1
技術的には、argumentsリストも変数になります。
Ruben Verborgh 2013

1
さて、あなたは割り当てaarguments[0]パラメータとして渡すことで。
Ruben Verborgh 2013

1
@RubenVerborghはい、しかしあなたはを作成せずarguments、その
割り当ては



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

ES5まで、2つの数値を交換するには、一時変数を作成してから交換する必要があります。しかしES6では、配列の構造化を使用して2つの数値を交換するのは非常に簡単です。例を参照してください。

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

ES6配列の非構造化は、2つの変数を交換するために使用されます。例を見る

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

より簡単な方法:

x === 1そしてy === 2; しかし、解体後、xis y、つまり2、およびyis x、つまり1です。


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.