ฉันมีตัวแปรสองตัวนี้:
var a = 1,
b = 2;
คำถามของฉันคือวิธีการสลับพวกเขา? เฉพาะตัวแปรนี้ไม่ใช่วัตถุใด ๆ
ฉันมีตัวแปรสองตัวนี้:
var a = 1,
b = 2;
คำถามของฉันคือวิธีการสลับพวกเขา? เฉพาะตัวแปรนี้ไม่ใช่วัตถุใด ๆ
คำตอบ:
นี่คือหนึ่งซับเพื่อสลับค่าของตัวแปรสองตัว
รับตัวแปรa
และb
:
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>
[a, b] = [b, a];
6:
Invalid left-hand side in assignment
ข้อผิดพลาดอยู่ในขณะนี้
ES6 (Firefox และ Chrome รองรับอยู่แล้ว (Destructuring Assignment Array Matching)):
let a = 5, b = 6;
[a, b] = [b, a];
console.log(`${a} ${b}`);
คุณสามารถทำได้:
var a = 1,
b = 2,
tmp;
tmp = a;
a = b;
b = tmp;
เพื่อความสามารถในการอ่านและการบำรุงรักษาไม่สามารถเอาชนะได้ (อย่างน้อยใน JavaScript) ทุกคนที่รักษารหัส (รวมถึงคุณหกเดือนนับจากนี้) จะรู้ว่าสิ่งที่เกิดขึ้น
เนื่องจากสิ่งเหล่านี้เป็นจำนวนเต็มคุณสามารถใช้เทคนิคฉลาด ๆ จำนวน1เพื่อสลับโดยไม่ต้องใช้ตัวแปรตัวที่สาม ตัวอย่างเช่นคุณสามารถใช้ตัวดำเนินการ bitor 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
ToInt32
วิธีการภายใน - ดูมาตรา 11.10 ของมาตรฐาน ECMAScript ) มันไม่ได้สร้างผลลัพธ์ที่ถูกต้องสำหรับค่าตัวเลขที่ไม่ใช่จำนวนเต็ม นอกจากนี้ยังแปลงค่าที่ไม่ใช่ตัวเลขเป็นจำนวนเต็ม 32 บิต หากคุณเริ่มต้นด้วยa = "hi"
และb = "there"
คุณจะจบลงด้วยและa == 0
b == 0
typeof a == 'boolean'
หรือa === false
ตัวอย่างเช่น ตัวเลขจริงทำงานได้ยกเว้นว่าพวกมันจะปูไปทางศูนย์และถูกปัดเศษเป็นจำนวนเต็มที่ใกล้เคียงที่สุด
อย่าใช้รหัสด้านล่าง มันเป็นไม่ได้วิธีที่แนะนำให้สลับค่าของทั้งสองตัวแปร (เพียงใช้ตัวแปรชั่วคราวสำหรับที่) มันแสดงให้เห็นถึงเคล็ดลับ JavaScript
การแก้ปัญหานี้ไม่ใช้ตัวแปรชั่วคราวอาร์เรย์ไม่มีเพียงคนเดียวนอกจากนี้และมันได้อย่างรวดเร็ว ในความเป็นจริงมันเป็นบางครั้งเร็วกว่าตัวแปรชั่วคราวบนหลายแพลตฟอร์ม
ใช้งานได้กับทุกหมายเลขไม่เคยล้นและจัดการกับตัวเรือนขอบเช่น Infinity และ NaN
a = b + (b=a, 0)
มันทำงานได้ในสองขั้นตอน:
(b=a, 0)
ตั้งb
ค่าเก่าa
และผลตอบแทน0
a = b + 0
กำหนดa
เป็นค่าเก่าของb
,
และมันถูกห่อเพื่อตั้งค่าลำดับความสำคัญก่อนหน้านี้ ตัวดำเนินการคอมม่าประเมินทั้งอาร์กิวเมนต์ (ในกรณีนี้b=a
และ0
) และส่งกลับค่าสุดท้าย (ในกรณีนี้0
) ดังนั้นที่นี่มันมีผลกระทบของการตั้งค่าใหม่b
เป็นค่าเก่าในขณะที่ผลผลิตa
0
ตั้งแต่ ES6 คุณสามารถสลับตัวแปรได้อย่างสวยงามยิ่งขึ้น:
var a = 1,
b = 2;
[a, b] = [b, a];
console.log('a:', a, 'b:', b); // a: 2 b: 1
นี่คือหนึ่งซับสมมติa
และb
มีอยู่แล้วและมีค่าที่จะต้องสลับ:
var c=a, a=b, b=c;
ตามที่ @ Kay พูดถึงสิ่งนี้จะทำงานได้ดีกว่าอาเรย์ (เกือบ 2 เท่าเร็ว)
var a, b, tmp;
a = 1
; b = 2
; tmp=a, a=b, b=tmp;
รสนิยมส่วนตัว.
ใช้ตัวแปรตัวที่สามเช่นนี้
var a = 1,
b = 2,
c = a;
a = b; // must be first or a and b end up being both 1
b = c;
DEMO - ใช้ตัวแปรตัวที่สาม
วิธี ES6 +: ตั้งแต่ ES6 คุณสามารถสลับตัวแปรได้อย่างสวยงามยิ่งขึ้น คุณสามารถใช้การจับคู่อาร์เรย์การกำหนดค่าการทำลาย มันเป็นเรื่องง่าย var a = 10 b = 20;
[a, b] = [b, a]
console.log (a, b) // 20 10
ในที่สุดคุณสามารถทำได้:
let a = 5;
let b = 10;
[a, b] = [b, a]; // ES6
console.log(a, b);
คุณสามารถใช้ตัวแปร swap ชั่วคราวหรือ XOR
a = a ^ b
b = a ^ b
a = a ^ b
นี่เป็นเพียงแนวคิดพื้นฐานเชิงตรรกะและทำงานในทุกภาษาที่สนับสนุนการดำเนินการ XOR
แก้ไข:ดูความคิดเห็น ลืมที่จะบอกว่าวิธีนี้ใช้ได้กับจำนวนเต็มเท่านั้น สันนิษฐานว่าตัวแปรจำนวนเต็มจากเธรดของคำถาม
คุณสามารถใช้การกำหนดรูปแบบการทำลาย ES6ดังนี้:
let a = 10;
let b = 20;
[a, b] = [b, a];
console.log(a, b); // a = 20, b = 10
เนื่องจากคำถามของคุณมีค่า "เฉพาะตัวแปรนี้เท่านั้นไม่มีวัตถุใด ๆ " คำตอบจะมีค่าเช่นกัน:
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/
การทำลายล้าง ES6:
ใช้อาร์เรย์: [a, b] = [b, a]; // my favorite
ใช้วัตถุ: {a, b} = {a:b, b:a}; // not bad neither
เราจะคิดถึงผู้เลียนแบบคลาสสิคเหล่านี้ได้อย่างไร
var a = 1, b = 2
a = ({a:b, _:(b=a)}).a;
และ
var a = 1, b = 2
a = (_=b,b=a,_);
อันสุดท้ายเผยให้เห็นตัวแปรทั่วโลก '_' แต่ที่ไม่ควรจะเป็นตามแบบแผนจาวาสคริปต์ทั่วไปคือการใช้มันเป็นตัวแปร 'ไม่สนใจ'
a = (_=b,b=a,_);
_
หมายถึงอะไร ทำไมมันไม่จำเป็นต้องประกาศ?
ฉันเห็นชนิดของการเขียนโปรแกรม olympiad ที่นี่ โซลูชันบรรทัดเดียวที่ซับซ้อนยิ่งขึ้น:
b = (function(){ a=b; return arguments[0]; })(a);
arguments
b = (function (x){ return x; })(a, a=b)
arguments
รายการก็จะเป็นตัวแปร
a
ให้arguments[0]
โดยผ่านมันเป็นพารามิเตอร์
arguments
และการมอบหมายของมันเกิดขึ้น "เบื้องหลัง"
การสลับบรรทัดเดี่ยว
a = a^b^(b^=(a^b));
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 // หรือของและเรียกใช้ด้วยรหัสชุดหนึ่ง
เราสามารถสลับ var ดังนี้:
var val1 = 117,
val2 = 327;
val2 = val1-val2;
console.log(val2);
val1 = val1-val2;
console.log(val1);
val2 = val1+val2;
console.log(val2);
ใน ES6 ตอนนี้มีการมอบหมายการทำลายล้างและคุณสามารถทำได้:
let a = 1;
let b = 2;
[b, a] = [a, b] // a = 2, b = 1
let a = 2, b = 4;
[b, a] = [a, b];
วิธีการ verbose เพิ่มเติมจะเป็น
let a = 2, b = 4;
a = [a, b];
b = a[0];
a = a[1];
มันง่ายมากใช้ไวยากรณ์การทำลายอาร์เรย์ของES6ซึ่ง[y, x] = [x, y]
สำหรับข้อมูลเพิ่มเติมโปรดดูที่ลิงค์นี้https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
จนถึง 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
เพราะฉันได้ยินวิธีนี้ทำงานช้าลง:
b = [a, a = b][0];
หากคุณวางแผนที่จะเก็บ vars ของคุณไว้ในวัตถุ (หรืออาร์เรย์) ฟังก์ชั่นนี้จะทำงาน:
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'}
เราสามารถใช้ IIFE เพื่อสลับสองค่าโดยไม่มีพารามิเตอร์เพิ่มเติม
var a = 5, b =8;
b = (function(a){
return a
}(a, a=b));
document.write("a: " + a+ " b: "+ b);
การทำลายอาร์เรย์ ES6 ใช้เพื่อสลับสองตัวแปร ดูตัวอย่าง
var [x,y]=[1,2];
[x,y]=[y,x];
ใช้วิธีที่ง่ายกว่าด้วย:
x === 1
และy === 2
; แต่หลังจาก destructuring, x
เป็นy
เช่น2
และy
เป็นเช่นx
1
สลับโดยใช้ Bitwise
let a = 10;
let b = 20;
a ^= b;
y ^= a;
a ^= b;
สลับบรรทัดเดียว "using Array"
[a, b] = [b, a]
(ฟังก์ชั่น (A, B) {b = A; a = B;}) (parseInt (a), parseInt (b));