Jak zamienić dwie zmienne w JavaScript


Odpowiedzi:


321

Oto jedna linijka służąca do zamiany wartości dwóch zmiennych.
Podane zmienne ai b:

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

Demonstracja poniżej:

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. Ale najkrótsza wersja będzie w ECMAScript 6: [a, b] = [b, a];.
dfsq

8
@Kay: Wydaje się również, że działa znacznie wolniej, używając tablicy zamiast trzeciej zmiennej: http://jsperf.com/swap-array-vs-variable Testowałem to tylko w Chrome. Nie mogłem jeszcze przetestować wersji ECMAScript 6, ponieważ obecnie Invalid left-hand side in assignment wyświetla błąd.
Nie,

2
@ FrançoisWahl Słuszna uwaga. Myślę, że większość odpowiedzi tutaj zadziała i są dość równoważne. Przypuszczam, że jest to kompromis między tymczasowym użyciem zmiennych, ilością kodu i szybkością.
showdev

3
@ FrançoisWahl cóż, nie przypuszczałbym, że to rozwiązanie jest o wiele wolniejsze. Zobacz też: jsperf.com/swap-array-vs-variable/3
kay - SE is evil

3
@showdev Przeczytaj cytat Dijkstry w odpowiedzi Teda Hoppa.
Brian McCutchon

185

ES6 (Firefox i Chrome już to obsługują (Destruifying Assignment Array Matching)):

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


2
ktoś zna nazwę tego rodzaju wymiany w es6?
derek

6
@derek - myślę, że to się nazywa dopasowywaniem tablic , forma przypisania destrukturyzacji .
Ted Hopp,

4
Wydaje się, że jest to około 35 razy wolniejsze niż metoda trzeciej zmiennej na nodejs 7.4.0 / win7 64. Ale na pewno jest fajna.
mkey


5
Od wersji V8 6.8, zamiana zmiennych ze zniszczeniem tablic powinna być tak szybka jak w przypadku zmiennej tymczasowej ( v8project.blogspot.com/2018/06/v8-release-68.html ).
Ruben Verborgh,

120

Możesz to zrobić:

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

Jeśli chodzi o czytelność i łatwość konserwacji, nie można tego przebić (przynajmniej w JavaScript). Każdy, kto zajmuje się kodem (w tym Ty za sześć miesięcy), będzie dokładnie wiedział, co się dzieje.

Ponieważ są to liczby całkowite, możesz również użyć dowolnej liczby sprytnych sztuczek 1 do zamiany bez używania trzeciej zmiennej. Na przykład możesz użyć bitowego operatora 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);

Nazywa się to algorytmem wymiany XOR. Jego teorię działania opisano w tym artykule w Wikipedii .

1 „Kompetentny programista jest w pełni świadomy ograniczonych rozmiarów własnej czaszki. Dlatego podchodzi do swojego zadania z pełną pokorą i unika sprytnych sztuczek, takich jak zaraza”. - Edsger W. Dijkstra


Xor będzie działał z każdym typem danych. To sztuczka odejmowania, która działa tylko z liczbami.
Rob Grant

11
@RobertGrant - Operator xor w JavaScript konwertuje swoje operandy na 32-bitowe liczby całkowite (przy użyciu ToInt32metody wewnętrznej - patrz Rozdział 11.10 standardu ECMAScript ). Nie daje poprawnych wyników dla wartości liczbowych innych niż całkowite. Konwertuje również wartości nienumeryczne na 32-bitowe liczby całkowite. Jeśli zaczniesz od a = "hi"i b = "there", otrzymasz a == 0i b == 0.
Ted Hopp,

1
Ta sztuczka działa z każdym typem danych, pod warunkiem, że nie masz nic przeciwko wynikowi w postaci liczby całkowitej; wartości są rzutowane automatycznie na int32s. Oznacza to, że może pracować z ciągami numerycznymi, wartościami logicznymi (0/1), null (0) i pustymi tablicami / obiektami (0). Chociaż oryginalny typ nie jest zachowywany, więc dotknięte wartości Booleans nie będą działać na przykład z typeof a == 'boolean'lub a === false. Liczby rzeczywiste działają, z wyjątkiem tego, że są wyliczane w kierunku zera w porównaniu z zaokrągleniem do najbliższej liczby całkowitej.
Beejor

1
@Beejor - Innymi słowy, działa z dowolnym typem danych, z wyjątkiem tego, że nie (chyba że są to wartości całkowite). W mojej książce „zamiana” oznacza „koniec z każdą zmienną mającą wartość, którą miała druga”, a nie „konwersja na int32, a następnie zamiana”.
Ted Hopp,

@TedHopp Fair wystarczająco. Miałem na myśli "działa" w kategoriach tego, że można do niego wrzucić dowolny typ danych, a nie jako dobre rozwiązanie do wymiany. Zgadzam się, że ogólnie nie jest to zbyt przydatne.
Beejor

58

Nie używaj poniższego kodu. To nie zalecanym sposobem, aby zamienić wartości dwóch zmiennych (wystarczy użyć zmiennej tymczasowej dla tego). Pokazuje tylko sztuczkę JavaScript.

To rozwiązanie nie wykorzystuje zmiennych tymczasowych, żadnych tablic, tylko jeden dodatek i jest szybkie . W rzeczywistości jest czasami szybszy niż zmienna tymczasowa na kilku platformach .
Działa dla wszystkich liczb, nigdy się nie przepełnia i obsługuje przypadki skrajne, takie jak Infinity i NaN.

a = b + (b=a, 0)

Działa w dwóch krokach:

  • (b=a, 0)ustawia bna starą wartość ai daje0
  • a = b + 0ustawia astarą wartośćb

5
Wersja temp var jest nieco szybsza i bardziej ogólna, a także bardziej czytelna. jsperf.com/swap-two-numbers-without-tmp-var/9
Antimony

Co w ogóle oznacza ta składnia ()? jak to daje 0?
Pete Alvin

8
Operator w nawiasach jest operatorem przecinka ,i został zawinięty w celu ustawienia prawa pierwszeństwa. Operator przecinka ocenia oba argumenty (w tym przypadku b=ai 0) i zwraca ostatni (w tym przypadku 0). Więc tutaj ma to wpływ na ustawienie nowej bwartości starej a, przy jednoczesnym uzyskaniu 0.
Ruben Verborgh

6
Czy mam rację, myśląc, że to działa tylko dla wartości liczbowych? Nie możesz tego używać z np. Var a = "hello" b = "world" as a = "world0".
Chris GW Green

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

19

Od wersji ES6 możesz także zamieniać zmienne bardziej elegancko:

var a = 1,
    b = 2;

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

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

18

Oto jeden-liner, zakładając ai bjuż istnieją i mają wartości, która chciałaby zostać zamienione:

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

Jak wspomniał @Kay, w rzeczywistości działa to lepiej niż metoda tablicowa (prawie 2x szybciej).


1
Podobnie jak moja idealna odpowiedź, po prostu wolę nie deklarować ponownie zmiennej a & b podczas zamiany i używać jawnej nazwy zmiennej „tmp”. Jak var a, b, tmp; a = 1:; b = 2; tmp=a, a=b, b=tmp; Własny gust.
Johnny Wong

10

Użyj trzeciej zmiennej, takiej jak ta:

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

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

DEMO - Korzystanie z trzeciej zmiennej



10

Metoda ES6 +: Od wersji ES6 można bardziej elegancko wymieniać zmienne. Możesz użyć destrukturyzacji dopasowywania tablic przypisania. Po prostu. var a = 10 b = 20;

[a, b] = [b, a]

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


10

Teraz możesz wreszcie zrobić:

let a = 5;
let b = 10;

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

console.log(a, b);


9

Możesz użyć tymczasowej zmiennej wymiany lub XOR.

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

To tylko podstawowa koncepcja logiczna i działa w każdym języku obsługującym operacje XOR.

edycja: zobacz komentarze. Zapomniałem powiedzieć, że działa to na pewno tylko w przypadku liczby całkowitej. Założono zmienne całkowite z wątku pytania


16
Działa na potrzeby wywiadów programistycznych i innych ogólnych spraw związanych z ciekawostkami. Pamiętaj jednak, że jest to raczej głupi sposób na zamianę wartości w prawdziwym życiu. Po pierwsze, w JS działa tylko z liczbami całkowitymi.
cHao

1
@Kay Co masz na myśli, mówiąc „coś nierealnego przez ostatnie 30 lat”? Używam operatorów bitowych, kiedy tylko ma to sens, co jest w rzeczywistości dość często (na przykład przełączanie nieznanej wartości logicznej)
Ben Harold

1
Operator @cHao Bitwise jest konsekwentnie (i zdecydowanie) najszybszy na moim komputerze: jsperf.com/swap-array-vs-variable/2
Ben Harold

3
@php_surgeon Zmieniłem trochę skrzypce, żeby kompilator nie mógł oznaczyć zmiennych jako martwych. jsperf.com/swap-array-vs-variable/3 . Rozwiązanie Temp Var jest teraz o 1/4 szybsze niż rozwiązanie XOR Swap
Kay - SE is evil

1
@Kay W sytuacjach, gdy coś jest stabilne, dobrze skomentowane, najszybsze i używane tylko w jednym lub dwóch miejscach, nie rozumiem, dlaczego nie byłoby to dobre w kodzie produkcyjnym. Generalnie operacje bitowe są trudną koncepcją, więc jeśli kod używa już ich kilku, opiekunowie i tak musieliby je znać. W większości przypadków jest to oczywiście przesada. Myślę tylko, że ogólne stwierdzenia nie zawsze są pomocne; wszystko ma swoje miejsce, nawet „goto” i „eval”.
Beejor


7

Ponieważ Twoje pytanie było cenne „Tylko te zmienne, a nie żadne przedmioty”, odpowiedź również będzie cenna:

var a = 1, b = 2

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

to sztuczka

I jak powiedział Rodrigo Assis, „może być krótsze”

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

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


1
Te same błędy, co odpowiedź @ DmiN.
kay - SE is evil

gdzie znajdujesz usterki? To nie jest honorowe
Abdennour TOUMI

2
@AbdennourToumi Myślę, że Kay odnosi się do faktu, że twoja odpowiedź działa tylko w przypadku liczb całkowitych.
showdev

1
@showdev: Przeczytaj jeszcze raz pytanie: „Tylko te zmienne, a nie żadne obiekty”… moja odpowiedź jest cenna jak pytanie. Proszę o oznaczenie komentarza. Powtarzam: to nie jest honorowe.
Abdennour TOUMI

1
Ta rozmowa jest dziwna. @AbdennourTOUMI - zmienne nie są tym samym, co liczby całkowite. Możesz mieć zmienne, które wskazują na obiekty, ciągi znaków, funkcje, null itp.
Rob Grant

6

Destrukturyzacja ES6:

Korzystanie z tablicy: [a, b] = [b, a]; // my favorite

Korzystanie z obiektu: {a, b} = {a:b, b:a}; // not bad neither


4

Jak moglibyśmy przegapić te klasyczne onelinery

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

I

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

Ostatnia z nich ujawnia zmienną globalną „_”, ale nie powinno to mieć znaczenia, ponieważ typowa konwencja javascript polega na używaniu jej jako zmiennej „dont care”.


1
W drugim jest literówka. Powinno byća = (_=b,b=a,_);
Mageek

Co oznacza podkreślenie _? Dlaczego nie wymaga deklaracji?
dzień

podkreślenie to tylko nazwa zmiennej globalnej, możesz ją zastąpić dowolną poprawną. np. a = (justsomething = b, b = a, justsomething)
Teemu Ikonen

6
O nie, nie używaj niezadeklarowanych zmiennych magic-global! To pewny sposób na okropne błędy w prawdziwym życiu.
oriadam

Każdy, kto używa underscore.js, będzie bardzo nieszczęśliwy, jeśli spróbuje drugiego.
Ted Hopp

3

Widzę tu coś w rodzaju olimpiady programowania. Jeszcze jedno skomplikowane rozwiązanie jednowierszowe:

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

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


2
Nie musisz używać spowolnienia arguments, po prostu zrób b = (function (x){ return x; })(a, a=b).
Ruben Verborgh,

1
@RubenVerborgh tak, ale z argumentami nie definiujemy trzeciej zmiennej!
Czerniow

1
Z technicznego punktu argumentswidzenia lista byłaby również zmienną.
Ruben Verborgh

1
Cóż, przypisujesz ado arguments[0], przekazując go jako parametr.
Ruben Verborgh,

1
@RubenVerborgh tak, ale nie tworzysz, argumentsa jego przypisanie odbywa się „za kulisami”
Czerniow


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

usuń lub skomentuj dwa // lub i uruchom z jednym zestawem kodu

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


2

Jesteśmy w stanie zamienić var ​​w ten sposób:

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

byłoby bardziej rozwlekłe podejście

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


1

Do ES5, aby zamienić dwie liczby, musisz utworzyć zmienną tymczasową, a następnie zamienić ją. Ale w ES6 bardzo łatwo jest zamienić dwie liczby za pomocą destrukturyzacji tablic. Zobacz przykład.

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

Ponieważ słyszę, że ta metoda działa wolniej:

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

Jeśli planujesz przechowywać swoje vary w obiekcie (lub tablicy), ta funkcja powinna działać:

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

Stosowanie:

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

Możemy użyć IIFE do zamiany dwóch wartości bez dodatkowego parametru

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

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


1

Destrukturyzacja tablicy ES6 jest używana do zamiany dwóch zmiennych. Zobacz przykład

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

Łatwiej to możliwe dzięki:

x === 1i y === 2; Ale po destrukturyzacji xjest y, czyli 2i yjest x, tj 1.


1

Zamień za pomocą Bitwise

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

Zamiana jednej linii „przy użyciu tablicy”

[a, b] = [b, a]

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.