JavaScript'te iki değişken nasıl değiştirilir?


Yanıtlar:


321

İşte iki değişkenin değerlerini değiştirmek için bir astar.
Verilen değişkenler ave b:

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

Aşağıdaki gösteri:

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. Ama en kısa versiyon ECMAScript'te 6 olacaktır: [a, b] = [b, a];.
dfsq

8
@Kay: Üçüncü değişken yerine bir dizi kullanmak da çok daha yavaş görünüyor: http://jsperf.com/swap-array-vs-variable Bunu yalnızca Chrome'da test ettim. ECMAScript 6 sürümünü henüz test edemedim.Invalid left-hand side in assignment hata .
Hayır

2
@ FrançoisWahl İyi bir nokta. Buradaki cevapların çoğunun işe yarayacağını ve oldukça eşdeğer olduğunu düşünüyorum. Geçici değişken kullanımı, kod miktarı ve hız arasında bir denge olduğunu düşünüyorum.
showdev

3
@ FrançoisWahl, bu çözümün çok daha yavaş olduğunu tahmin etmezdim. Ayrıca bakınız: jsperf.com/swap-array-vs-variable/3
kay - SE kötülüktür

3
@showdev Ted Hopp'un cevabındaki Dijkstra alıntısını okuyun.
Brian McCutchon

185

ES6 (Firefox ve Chrome zaten destekliyor (Yıkıcı Atama Dizisi Eşleşmesi)):

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


2
Herkes es6 böyle bir takas adını biliyor mu?
derek

6
@derek - Sanırım buna dizi eşleştirme deniyor , bir çeşit yıkım görevi .
Ted Hopp

4
Bu, 7.4.0 / win7 64 düğümündeki üçüncü değişken yöntemden yaklaşık 35 kat daha yavaş görünmektedir. Ancak emin olun.
mkey


5
V8 sürüm 6.8'den bu yana, dizi yıkımına sahip değişkenleri değiştirmek, geçici bir değişkenle ( v8project.blogspot.com/2018/06/v8-release-68.html ) hızlı olmalıdır .
Ruben Verborgh

120

Bunu yapabilirsiniz:

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

Okunabilirlik ve bakım kolaylığı için, bu işlem yenilmez (en azından JavaScript'te). Kodu koruyan herkes (şu andan itibaren altı ay dahil) neler olduğunu tam olarak bilecek.

Bunlar tamsayı olduğundan, üçüncü bir değişken kullanmadan takas etmek için istediğiniz sayıda akıllı numara 1 kullanabilirsiniz. Örneğin, bitsel x veya operatörünü kullanabilirsiniz:

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

Buna XOR takas algoritması denir. Çalışma teorisi bu Wikipedia makalesinde açıklanmıştır .

1 "Yetkili programcı kendi kafatasının sınırlı büyüklüğünün tamamen farkında. Bu nedenle görevine tam tevazu ile yaklaşıyor ve veba gibi akıllı numaralardan kaçınıyor." - Edsger W.Dijkstra


Xor, herhangi bir veri türüyle çalışır. Sadece rakamlarla çalışacak çıkarma hilesi.
Rob Grant

11
@RobertGrant - JavaScript'teki xor operatörü işlenenlerini 32 bit tamsayılara dönüştürür ( ToInt32dahili yöntemi kullanarak - ECMAScript standardının 11.10 bölümüne bakın ). Tamsayı olmayan sayısal değerler için doğru sonuçları üretmez. Ayrıca sayısal olmayan değerleri 32 bit tamsayılara dönüştürür. Eğer başlarsanız a = "hi"ve b = "there", ile sona a == 0ve b == 0.
Ted Hopp

1
Bu hile, bir tamsayı sonucuna aldırmamanız koşuluyla, herhangi bir veri türüyle çalışır; değerler int32s'ye otomatik olarak çevrilir. Bu, sayısal dizeler, Booleans (0/1), null (0) ve boş diziler / nesnelerle (0) çalışabileceği anlamına gelir. Orijinal tür korunmasa da, etkilenen Booleans typeof a == 'boolean'veya a === falseörneğin çalışmaz . Gerçek sayılar çalışır, ancak en yakın tamsayıya yuvarlanmış olarak sıfıra doğru katlanırlar.
Beejor

1
@Beejor - Başka bir deyişle, (tamsayı değerler olmadıkça) dışında herhangi bir veri türüyle çalışır. Kitabımda "takas" her değişkenin "int32'ye dönüştürüp takas" değil, diğerinin sahip olduğu değere sahip olduğu anlamına gelir.
Ted Hopp

@TedHopp Yeterince adil. Ben iyi bir takas çözümü olarak çalışıyor gibi değil, herhangi bir veri türü atmak gerçeği açısından "çalışır" demek istedim. Genel olarak çok yararlı olmadığını kabul ediyorum.
Beejor

58

Aşağıdaki kodu kullanmayın. İki değişkenin değerlerini değiştirmek için önerilen yol bu değildir ( bunun için geçici bir değişken kullanın ). Sadece bir JavaScript numarası gösterir.

Bu çözümde geçici değişkenler, diziler kullanılmaz, yalnızca bir ek kullanılır ve hızlıdır . Aslında, bazen birkaç platformdaki geçici bir değişkenden daha hızlıdır .
Tüm sayılar için çalışır, asla taşmaz ve Infinity ve NaN gibi kenar durumlarını işler.

a = b + (b=a, 0)

İki adımda çalışır:

  • (b=a, 0)setler beski değerine ave verim0
  • a = b + 0aeski değerine ayarlanırb

5
Temp var sürümü biraz daha hızlı ve daha genel ve daha okunabilir. jsperf.com/swap-two-numbers-without-tmp-var/9
Antimon

Bu () sözdizimi ne anlama geliyor? nasıl 0 verir?
Pete Alvin

8
Parantez içindeki operatör virgül operatörüdür ,ve öncelik hakkını ayarlamak için kaydırılmıştır. Virgül operatörü her iki bağımsız değişkenini de (bu durumda b=ave 0) değerlendirir ve sonuncusunu (bu durumda 0) döndürür . Yani burada, yeniyi verirken beski değerini eski değerine ayarlama etkisi vardır . a0
Ruben Verborgh

6
Bunun sadece sayısal değer için uygun olduğunu düşünmekte haklı mıyım? Bunu örneğin = a = "dünya0" olarak var a = "merhaba" b = "dünya" ile kullanamazsınız.
Chris GW Green

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

19

ES6'dan beri değişkenleri daha zarif bir şekilde değiştirebilirsiniz:

var a = 1,
    b = 2;

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

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

18

Burada tek liner varsayılarak var ave bzaten var ve takas edilmesi gerek değerlere sahiptir:

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

@Kay'ın belirttiği gibi, bu aslında dizi yolundan daha iyi performans gösterir (neredeyse 2 kat daha hızlı).


1
Benim ideal cevabım gibi, ben sadece takas sırasında a & b değişkenini yeniden bildirmemeyi tercih ederim ve açık değişken adı "tmp" kullanın. Gibi var a, b, tmp; a = 1:; b = 2; tmp=a, a=b, b=tmp; Kişisel zevk.
Johnny Wong

10

Bunun gibi üçüncü bir değişken kullanın:

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

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

DEMO - Üçüncü bir değişken kullanma



10

ES6 + yöntemi: ES6'dan beri değişkenleri daha zarif bir şekilde değiştirebilirsiniz. Yıkıcı atama dizisi eşleşmesini kullanabilirsiniz. Basitçe. var a = 10 b = 20;

[a, b] = [b, a]

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


10

Sonunda şunları yapabilirsiniz:

let a = 5;
let b = 10;

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

console.log(a, b);


9

Geçici bir takas değişkeni veya XOR kullanabilirsiniz.

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

Bu sadece temel bir mantıksal kavramdır ve XOR çalışmasını destekleyen her dilde çalışır.

edit: Yorumlara bakın. Bunun sadece tamsayı ile çalıştığını söylemeyi unuttum. Sorunun evresinden tamsayı değişkenleri olduğu varsayıldı


16
Röportajları ve diğer genel trivia vakalarını programlama çalışmaları. Bununla birlikte, bunun gerçek hayatta değerleri değiştirmenin oldukça aptalca bir yolu olduğunu unutmayın. Birincisi, JS'de, yalnızca tamsayılarla çalışır.
cHao

1
@Kay "Son 30 yıldır gerçek olmayan bir şey değil" ile ne demek istiyorsun? Her ne kadar mantıklı olduğunda bitsel operatörler kullanırım, ki bu aslında oldukça sık (örneğin bilinmeyen bir boole'yi değiştirir)
Ben Harold

1
@cHao Bitwise operatörü makinemde sürekli olarak (ve bugüne kadar) en hızlı: jsperf.com/swap-array-vs-variable/2
Ben Harold

3
@php_surgeon Derleyicinin değişkenleri ölü olarak işaretleyememesi için kemanı biraz değiştirdim. jsperf.com/swap-array-vs-variable/3 . Temp var çözümü şimdi xor takas çözümünden 1/4 daha hızlı
kay - SE kötü

1
@Kay Bir şeyin kararlı, iyi yorumlanmış, en hızlı teknik olduğu ve sadece bir veya iki yerde kullanıldığı durumlarda, üretim kodunda neden iyi olmayacağını anlamıyorum. Genel olarak bitsel operasyonlar zor bir kavramdır, bu nedenle kod zaten bir demet kullanıyorsa, bakımcıların bunlara aşina olması gerekir. Çoğu durumda, açıkça abartılı. Sadece battaniye ifadelerinin her zaman yardımcı olmadığını düşünüyorum; her şeyin bir yeri vardır, hatta "git" ve "eval".
Beejor


7

Sorunuz değerli olduğu için "Sadece bu değişkenler, herhangi bir nesne değil.", Cevap da değerli olacaktır:

var a = 1, b = 2

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

bu bir hile

Ve Rodrigo Assis'in dediği gibi "daha kısa olabilir"

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

Demo: http://jsfiddle.net/abdennour/2jJQ2/


1
@ DmiN'nin cevabı ile aynı hatalar.
kay - SE kötülük

nerede hata bulabilirim? Onurlu değil
Abdennour TOUMI

2
@AbdennourToumi Bence Kay, cevabınızın sadece tamsayılarla çalıştığı gerçeğinden bahsediyor.
showdev

1
@showdev: Lütfen tekrar okuyun soru: "Herhangi bir nesne değil, sadece bu değişkenler" .... Cevabım soru olarak değerlidir. Sizden yorumu işaretlemenizi istiyorum Tekrar ediyorum: şerefli değil.
Abdennour TOUMI

1
Bu konuşma tuhaf. @AbdennourTOUMI - değişkenler tamsayılarla aynı değildir. Nesneleri, dizeleri, işlevleri, boş, vb.
Rob Grant

6

ES6 Yıkım:

Dizi kullanma: [a, b] = [b, a]; // my favorite

Bir nesne kullanma: {a, b} = {a:b, b:a}; // not bad neither


4

Bu klasik onelinerleri nasıl özleyebiliriz?

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

Ve

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

Sonuncusu '_' genel değişkenini ortaya koyar, ancak tipik javascript kuralı 'umurumda değil' değişkeni olarak kullanmak önemli değildir.


1
İkincisinde bir yazım hatası var. O olmalıa = (_=b,b=a,_);
Mageek

Alt çizgi ne anlama _geliyor? Neden beyan edilmesine gerek yok?
gün

alt çizgi sadece global değişken adıdır, geçerli herhangi biriyle değiştirebilirsiniz. örneğin a = (justsomething = b, b = a, justsomething)
Teemu Ikonen

6
Oh hayır, bildirilmemiş sihirli-küresel değişkenler kullanmayın! Bu, gerçek hayatta korkunç böcekler için kesin bir yoldur.
oriadam

Kullanan herkes underscore.js onlar ikincisini deneyin eğer çok mutsuz olacak.
Ted Hopp

3

Burada bir tür olimpiyat programlaması görüyorum. Bir tane daha zor tek satırlık çözüm:

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

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


2
Yavaş kullanmaya gerek yok arguments, sadece yap b = (function (x){ return x; })(a, a=b).
Ruben Verborgh

1
@RubenVerborgh evet ama argümanlarla üçüncü bir değişken tanımlamıyoruz!
Cherniv

1
Teknik olarak, argumentsliste de bir değişken olacaktır.
Ruben Verborgh

1
Eh, atamak aiçin arguments[0]bir parametre olarak geçirerek.
Ruben Verborgh

1
@RubenVerborgh evet, ancak oluşturmuyorsunuz argumentsve
ataması


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 // veya'ları kaldırın veya yorum yapın ve bir kod kümesiyle çalıştırın

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


2

Biz böyle değiş tokuş edebiliyoruz:

var val1 =  117,
    val2 = 327;

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

2

ES6'da şimdi yıkıcı atama var ve şunları yapabilirsiniz:

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

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

daha ayrıntılı bir yaklaşım

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


1

ES5'e kadar, iki sayıyı değiş tokuş etmek için, bir temp değişkeni oluşturmanız ve daha sonra değiştirmeniz gerekir. Ancak ES6'da dizi yıkımını kullanarak iki sayıyı değiştirmek çok kolay. Örneğe bakın.

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

Çünkü bu yöntem daha yavaş çalışır duydum:

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

Değişkenlerinizi bir nesneye (veya diziye) depolamayı planlıyorsanız, bu işlev çalışmalıdır:

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

Kullanımı:

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

Ek parametre olmadan iki değeri değiştirmek için IIFE'yi kullanabiliriz

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

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


1

ES6 dizi yıkımı iki değişkeni değiştirmek için kullanılır. Örneğe bakın

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

Aşağıdakilerle daha kolay yol:

x === 1ve y === 2; Ama Strüktür kırıcı sonra xise yyani 2, ve yolduğunu xyani 1.


1

Bitwise'u kullanarak değiştir

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

Tek satır Takas "kullanma Array"

[a, b] = [b, a]

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.