อาร์เรย์มีวิธีการมากมาย เพื่อให้สิ่งต่าง ๆ ง่ายขึ้น ในบทนี้พวกเขาจะแบ่งออกเป็นกลุ่ม
เรารู้วิธีการที่เพิ่มและลบรายการตั้งแต่ต้นหรือสิ้นสุดแล้ว:
arr.push(...items)
– เพิ่มรายการต่อท้าย
arr.pop()
– แยกรายการออกจากส่วนท้าย
arr.shift()
– แยกรายการจากจุดเริ่มต้น
arr.unshift(...items)
– เพิ่มรายการไปที่จุดเริ่มต้น
นี่คือบางส่วนอื่น ๆ
จะลบองค์ประกอบออกจากอาร์เรย์ได้อย่างไร?
อาร์เรย์เป็นวัตถุดังนั้นเราจึงลองใช้ delete
:
ให้ arr = ["ฉัน", "ไป", "บ้าน"]; ลบ arr[1]; // ลบ "ไป" การแจ้งเตือน (arr[1] ); // ไม่ได้กำหนด // ตอนนี้ arr = ["ฉัน", , "บ้าน"]; การแจ้งเตือน( arr.length ); // 3
องค์ประกอบถูกลบออกไปแล้ว แต่อาร์เรย์ยังคงมี 3 องค์ประกอบ เราจะเห็นได้ว่า arr.length == 3
นั่นเป็นเรื่องปกติ เพราะ delete obj.key
จะลบค่าด้วย key
มันคือทั้งหมดที่มันไม่ ดีสำหรับวัตถุ แต่สำหรับอาร์เรย์ เรามักจะต้องการให้องค์ประกอบที่เหลือเปลี่ยนและครอบครองตำแหน่งที่ว่าง เราคาดว่าจะมีอาร์เรย์ที่สั้นลงในขณะนี้
ดังนั้นควรใช้วิธีพิเศษ
วิธี arr.splice เป็นวิธีการของ Swiss Army สำหรับอาร์เรย์ มันสามารถทำทุกอย่าง: แทรก ลบ และแทนที่องค์ประกอบ
ไวยากรณ์คือ:
arr.splice(เริ่มต้น[, DeleteCount, elem1, ..., elemN])
มันแก้ไข arr
โดยเริ่มจากดัชนี start
: ลบองค์ประกอบ deleteCount
แล้วแทรก elem1, ..., elemN
ที่ตำแหน่งของพวกเขา ส่งกลับอาร์เรย์ขององค์ประกอบที่ถูกลบออก
วิธีนี้ง่ายต่อการเข้าใจด้วยตัวอย่าง
เริ่มต้นด้วยการลบ:
ให้ arr = ["ฉัน", "ศึกษา", "JavaScript"]; arr.ประกบ(1, 1); // จากดัชนี 1 ลบ 1 องค์ประกอบ แจ้งเตือน(arr); // ["ฉัน", "จาวาสคริปต์"]
ง่ายใช่มั้ย? เริ่มต้นจากดัชนี 1
จะลบ 1
องค์ประกอบ
ในตัวอย่างถัดไป เราลบ 3 องค์ประกอบออกและแทนที่ด้วยอีก 2 องค์ประกอบ:
ให้ arr = ["ฉัน", "ศึกษา", "JavaScript", "ถูกต้อง", "ตอนนี้"]; // ลบ 3 องค์ประกอบแรกออกแล้วแทนที่ด้วยองค์ประกอบอื่น arr.splice(0, 3, "มาเถอะ", "เต้นรำ"); alert( arr ) // ตอนนี้ ["มาเถอะ", "เต้นรำ", "ถูกต้อง", "ตอนนี้"]
ที่นี่เราจะเห็นว่า splice
ส่งกลับอาร์เรย์ขององค์ประกอบที่ถูกลบออก:
ให้ arr = ["ฉัน", "ศึกษา", "JavaScript", "ถูกต้อง", "ตอนนี้"]; // ลบ 2 องค์ประกอบแรกออก ให้ลบออก = arr.splice(0, 2); การแจ้งเตือน (ลบออก); // "I", "study" <-- อาร์เรย์ขององค์ประกอบที่ถูกลบออก
วิธี splice
ยังสามารถแทรกองค์ประกอบต่างๆ ได้โดยไม่ต้องถอดออก เพื่อสิ่งนั้น เราต้องตั้ง deleteCount
เป็น 0
:
ให้ arr = ["ฉัน", "ศึกษา", "JavaScript"]; // จากดัชนี 2 // ลบ 0 // จากนั้นใส่ "ซับซ้อน" และ "ภาษา" arr.splice(2, 0, "ซับซ้อน", "ภาษา"); แจ้งเตือน(arr); // "ฉัน", "เรียน", "ซับซ้อน", "ภาษา", "จาวาสคริปต์"
อนุญาตให้ใช้ดัชนีเชิงลบ
ที่นี่และในวิธีการอาร์เรย์อื่นๆ อนุญาตให้ใช้ดัชนีเชิงลบได้ โดยจะระบุตำแหน่งจากจุดสิ้นสุดของอาร์เรย์ ดังตัวอย่างต่อไปนี้
ให้ arr = [1, 2, 5]; // จากดัชนี -1 (หนึ่งขั้นตอนจากจุดสิ้นสุด) // ลบ 0 องค์ประกอบ // จากนั้นใส่ 3 และ 4 arr.ประกบ(-1, 0, 3, 4); แจ้งเตือน(arr); // 1,2,3,4,5
วิธีการ arr.slice นั้นง่ายกว่า arr.splice
ที่ดูคล้ายกันมาก
ไวยากรณ์คือ:
arr.slice([เริ่มต้น], [จบ])
มันจะส่งคืนอาร์เรย์ใหม่ที่คัดลอกไปยังรายการทั้งหมดตั้งแต่ดัชนี start
to end
(ไม่รวม end
) ทั้ง start
และ end
อาจเป็นค่าลบได้ ในกรณีนี้จะถือว่าตำแหน่งจากจุดสิ้นสุดอาร์เรย์
มันคล้ายกับเมธอดสตริง str.slice
แต่แทนที่จะสร้างสตริงย่อย กลับสร้างอาร์เรย์ย่อย
ตัวอย่างเช่น:
ให้ arr = ["t", "e", "s", "t"]; การแจ้งเตือน ( arr.slice (1, 3) ); // e,s (คัดลอกจาก 1 ถึง 3) การแจ้งเตือน( arr.slice(-2) ); // s,t (คัดลอกจาก -2 จนจบ)
นอกจากนี้เรายังสามารถเรียกมันได้โดยไม่ต้องมีข้อโต้แย้ง: arr.slice()
สร้างสำเนาของ arr
ซึ่งมักใช้เพื่อรับสำเนาสำหรับการแปลงเพิ่มเติมที่ไม่ควรส่งผลกระทบต่ออาร์เรย์ดั้งเดิม
วิธีการ arr.concat สร้างอาร์เรย์ใหม่ที่มีค่าจากอาร์เรย์อื่นและรายการเพิ่มเติม
ไวยากรณ์คือ:
arr.concat (arg1, arg2...)
ยอมรับอาร์กิวเมนต์จำนวนเท่าใดก็ได้ ไม่ว่าจะเป็นอาร์เรย์หรือค่าก็ตาม
ผลลัพธ์คืออาร์เรย์ใหม่ที่มีรายการจาก arr
จากนั้น arg1
, arg2
เป็นต้น
หากอาร์กิวเมนต์ argN
เป็นอาร์เรย์ องค์ประกอบทั้งหมดจะถูกคัดลอก มิฉะนั้น อาร์กิวเมนต์เองจะถูกคัดลอก
ตัวอย่างเช่น:
ให้ arr = [1, 2]; // สร้างอาร์เรย์จาก: arr และ [3,4] การแจ้งเตือน( arr.concat([3, 4]) ); // 1,2,3,4 // สร้างอาร์เรย์จาก: arr และ [3,4] และ [5,6] การแจ้งเตือน( arr.concat([3, 4], [5, 6]) ); // 1,2,3,4,5,6 // สร้างอาร์เรย์จาก: arr และ [3,4] จากนั้นเพิ่มค่า 5 และ 6 การแจ้งเตือน( arr.concat([3, 4], 5, 6) ); // 1,2,3,4,5,6
โดยปกติจะคัดลอกเฉพาะองค์ประกอบจากอาร์เรย์เท่านั้น ออบเจ็กต์อื่นๆ แม้ว่าจะดูเหมือนอาร์เรย์ก็ตาม จะถูกเพิ่มโดยรวม:
ให้ arr = [1, 2]; ให้ arrayLike = { 0: "บางสิ่งบางอย่าง" ความยาว: 1 - การแจ้งเตือน ( arr.concat (arrayLike) ); // 1,2,[วัตถุวัตถุ]
…แต่หากวัตถุที่มีลักษณะคล้ายอาร์เรย์มีคุณสมบัติพิเศษ Symbol.isConcatSpreadable
ก็จะถือว่าเป็นอาร์เรย์โดย concat
: องค์ประกอบจะถูกเพิ่มแทน:
ให้ arr = [1, 2]; ให้ arrayLike = { 0: "บางสิ่งบางอย่าง" 1: "อย่างอื่น" [Symbol.isConcatSpreadable]: จริง, ความยาว: 2 - การแจ้งเตือน ( arr.concat (arrayLike) ); // 1,2 บางอย่างอย่างอื่น
เมธอด arr.forEach อนุญาตให้เรียกใช้ฟังก์ชันสำหรับทุกองค์ประกอบของอาร์เรย์
ไวยากรณ์:
arr.forEach (ฟังก์ชั่น (รายการ, ดัชนี, อาร์เรย์) { // ... ทำบางอย่างกับไอเท็ม -
ตัวอย่างเช่น นี่จะแสดงแต่ละองค์ประกอบของอาร์เรย์:
// สำหรับการแจ้งเตือนการโทรแต่ละองค์ประกอบ ["บิลโบ", "แกนดัล์ฟ", "นาซกุล"].forEach(แจ้งเตือน);
และโค้ดนี้ละเอียดมากขึ้นเกี่ยวกับตำแหน่งในอาร์เรย์เป้าหมาย:
["บิลโบ", "แกนดัล์ฟ", "นาซกุล"].forEach((รายการ, ดัชนี, อาร์เรย์) => { alert(`${item} อยู่ที่ดัชนี ${index} ใน ${array}`); -
ผลลัพธ์ของฟังก์ชัน (หากส่งคืน) จะถูกละเว้นและละเว้น
ตอนนี้เรามาดูวิธีการค้นหาในอาร์เรย์กันดีกว่า
เมธอด arr.indexOf และ arr.include มีไวยากรณ์คล้ายกัน และทำในลักษณะเดียวกับวิธีสตริง แต่ดำเนินการกับรายการแทนอักขระ:
arr.indexOf(item, from)
– ค้นหา item
ที่เริ่มต้นจากดัชนี from
และส่งกลับดัชนีที่พบ มิฉะนั้น -1
arr.includes(item, from)
– ค้นหา item
ที่เริ่มต้นจากดัชนี from
จะส่งคืนค่า true
หากพบ
โดยปกติแล้ว วิธีการเหล่านี้จะใช้กับอาร์กิวเมนต์เดียวเท่านั้น: item
ที่จะค้นหา ตามค่าเริ่มต้น การค้นหาจะมาจากจุดเริ่มต้น
ตัวอย่างเช่น:
ให้ arr = [1, 0, false]; การแจ้งเตือน ( arr.indexOf(0) ); // 1 การแจ้งเตือน( arr.indexOf(false) ); // 2 การแจ้งเตือน ( arr.indexOf(null) ); // -1 การแจ้งเตือน( arr.includes(1) ); // จริง
โปรดทราบว่า indexOf
ใช้ความเท่าเทียมกันที่เข้มงวด ===
สำหรับการเปรียบเทียบ ดังนั้น หากเราค้นหา false
ก็จะพบว่าเป็น false
ทุกประการและไม่ใช่ศูนย์
หากเราต้องการตรวจสอบว่ามี item
อยู่ในอาร์เรย์หรือไม่และไม่ต้องการดัชนี แนะนำให้ใช้ arr.includes
วิธีการ arr.lastIndexOf เหมือนกับ indexOf
แต่ค้นหาจากขวาไปซ้าย
ให้ผลไม้ = ['แอปเปิ้ล', 'ส้ม', 'แอปเปิ้ล'] การแจ้งเตือน (fruits.indexOf('Apple') ); // 0 (แอปเปิ้ลตัวแรก) การแจ้งเตือน (fruits.lastIndexOf('Apple') ); // 2 (แอปเปิ้ลตัวสุดท้าย)
วิธี includes
จะจัดการ NaN
ได้อย่างถูกต้อง
คุณสมบัติเล็กน้อย แต่น่าสังเกตของ includes
คือมันจัดการ NaN
ได้อย่างถูกต้อง ไม่เหมือน indexOf
:
const arr = [น่าน]; การแจ้งเตือน ( arr.indexOf(NaN) ); // -1 (ผิด ควรเป็น 0) alert( arr.includes(NaN) );// จริง (ถูกต้อง)
นั่นเป็นเพราะว่า includes
ถูกเพิ่มลงใน JavaScript ในเวลาต่อมา และใช้อัลกอริธึมการเปรียบเทียบที่ทันสมัยยิ่งขึ้นเป็นการภายใน
ลองนึกภาพเรามีวัตถุมากมาย เราจะค้นหาวัตถุที่มีเงื่อนไขเฉพาะได้อย่างไร?
ที่นี่เมธอด arr.find(fn) มีประโยชน์มาก
ไวยากรณ์คือ:
ให้ผลลัพธ์ = arr.find (ฟังก์ชั่น (รายการ, ดัชนี, อาร์เรย์) { // หากคืนค่าเป็นจริง รายการจะถูกส่งคืนและการวนซ้ำจะหยุดลง // สำหรับสถานการณ์ที่ผิดพลาดส่งคืนไม่ได้กำหนด -
ฟังก์ชันนี้ถูกเรียกใช้สำหรับองค์ประกอบของอาร์เรย์ ทีละรายการ:
item
คือองค์ประกอบ
index
คือดัชนีของมัน
array
ก็คืออาร์เรย์นั่นเอง
หากส่งคืน true
การค้นหาจะหยุดลง item
จะถูกส่งคืน หากไม่พบสิ่งใดเลย ระบบจะส่งคืน undefined
ตัวอย่างเช่น เรามีอาร์เรย์ของผู้ใช้ โดยแต่ละรายมีฟิลด์ id
และ name
มาหาอันที่มี id == 1
:
ให้ผู้ใช้ = [ {id: 1 ชื่อ: "จอห์น"}, {id: 2 ชื่อ: "พีท"}, {id: 3 ชื่อ: "แมรี่"} - ให้ผู้ใช้ = users.find(item => item.id == 1); การแจ้งเตือน (ชื่อผู้ใช้); // จอห์น
ในชีวิตจริง อาร์เรย์ของวัตถุเป็นเรื่องธรรมดา ดังนั้นวิธี find
จึงมีประโยชน์มาก
โปรดทราบว่าในตัวอย่างที่เราจัดเตรียมไว้เพื่อ find
ฟังก์ชัน item => item.id == 1
ที่มีหนึ่งอาร์กิวเมนต์ นั่นเป็นเรื่องปกติ อาร์กิวเมนต์อื่นๆ ของฟังก์ชันนี้ไม่ค่อยได้ใช้
เมธอด arr.findIndex มีไวยากรณ์เหมือนกัน แต่ส่งคืนดัชนีที่พบองค์ประกอบ แทนที่จะเป็นองค์ประกอบนั้นเอง หากไม่พบสิ่งใดเลย ค่า -1
จะถูกส่งกลับ
เมธอด arr.findLastIndex เหมือนกับ findIndex
แต่ค้นหาจากขวาไปซ้าย คล้ายกับ lastIndexOf
นี่คือตัวอย่าง:
ให้ผู้ใช้ = [ {id: 1 ชื่อ: "จอห์น"}, {id: 2 ชื่อ: "พีท"}, {id: 3 ชื่อ: "แมรี่"}, {id: 4 ชื่อ: "จอห์น"} - // ค้นหาดัชนีของจอห์นคนแรก alert(users.findIndex(user => user.name == 'John')); // 0 // ค้นหาดัชนีของจอห์นคนสุดท้าย alert(users.findLastIndex(user => user.name == 'จอห์น')); // 3
find
วิธีการค้นหาองค์ประกอบเดียว (แรก) ที่ทำให้ฟังก์ชันส่งกลับ true
หากมีจำนวนมากเราสามารถใช้ arr.filter(fn) ได้
ไวยากรณ์คล้ายกับ find
แต่ filter
ส่งคืนอาร์เรย์ขององค์ประกอบที่ตรงกันทั้งหมด:
ให้ผลลัพธ์ = arr.filter (ฟังก์ชั่น (รายการ, ดัชนี, อาร์เรย์) { // ถ้ารายการจริงถูกผลักไปยังผลลัพธ์และการวนซ้ำดำเนินต่อไป // ส่งคืนอาร์เรย์ว่างหากไม่พบสิ่งใด -
ตัวอย่างเช่น:
ให้ผู้ใช้ = [ {id: 1 ชื่อ: "จอห์น"}, {id: 2 ชื่อ: "พีท"}, {id: 3 ชื่อ: "แมรี่"} - // ส่งคืนอาร์เรย์ของผู้ใช้สองคนแรก ให้ someUsers = users.filter(item => item.id < 3); การแจ้งเตือน (someUsers.length); // 2
เรามาดูวิธีการที่แปลงและเรียงลำดับอาร์เรย์ใหม่กัน
เมธอด arr.map เป็นหนึ่งในวิธีที่มีประโยชน์และมักใช้บ่อยที่สุด
โดยเรียกฟังก์ชันสำหรับแต่ละองค์ประกอบของอาร์เรย์และส่งกลับอาร์เรย์ของผลลัพธ์
ไวยากรณ์คือ:
ให้ผลลัพธ์ = arr.map (ฟังก์ชั่น (รายการ, ดัชนี, อาร์เรย์) { // ส่งกลับค่าใหม่แทนรายการ -
ตัวอย่างเช่น ที่นี่เราแปลงแต่ละองค์ประกอบให้มีความยาว:
ให้ lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length); การแจ้งเตือน (ความยาว); // 5,7,6
การเรียก arr.sort() จะเรียงลำดับอาร์เรย์ ในตำแหน่ง โดยเปลี่ยนลำดับองค์ประกอบ
นอกจากนี้ยังส่งคืนอาร์เรย์ที่เรียงลำดับแล้ว แต่โดยปกติแล้วค่าที่ส่งคืนจะถูกละเว้น เนื่องจาก arr
ได้รับการแก้ไขแล้ว
ตัวอย่างเช่น:
ให้ arr = [ 1, 2, 15 ]; // วิธีการจัดลำดับเนื้อหาของ arr ใหม่ arr.เรียงลำดับ(); แจ้งเตือน(arr); // 1, 15, 2
คุณสังเกตเห็นสิ่งแปลก ๆ ในผลลัพธ์หรือไม่?
ลำดับกลายเป็น 1, 15, 2
. ไม่ถูกต้อง. แต่ทำไม?
รายการจะถูกจัดเรียงเป็นสตริงตามค่าเริ่มต้น
แท้จริงแล้ว องค์ประกอบทั้งหมดจะถูกแปลงเป็นสตริงเพื่อการเปรียบเทียบ สำหรับสตริง จะใช้การเรียงลำดับพจนานุกรมและ "2" > "15"
หากต้องการใช้การเรียงลำดับของเราเอง เราจำเป็นต้องระบุฟังก์ชันเป็นอาร์กิวเมนต์ของ arr.sort()
ฟังก์ชันควรเปรียบเทียบค่าใดก็ได้สองค่าและส่งกลับ:
ฟังก์ชั่นเปรียบเทียบ (a, b) { ถ้า (a > b) ส่งกลับ 1; // ถ้าค่าแรกมากกว่าค่าที่สอง ถ้า (a == b) ส่งกลับ 0; // ถ้าค่าเท่ากัน ถ้า (a < b) กลับ -1; // ถ้าค่าแรกน้อยกว่าค่าที่สอง -
ตัวอย่างเช่น หากต้องการเรียงลำดับเป็นตัวเลข:
ฟังก์ชั่น comparisonNumeric (a, b) { ถ้า (a > b) ส่งกลับ 1; ถ้า (a == b) ส่งกลับ 0; ถ้า (a < b) กลับ -1; - ให้ arr = [ 1, 2, 15 ]; arr.sort(เปรียบเทียบตัวเลข); การแจ้งเตือน(arr); // 1, 2, 15
ตอนนี้มันทำงานได้ตามที่ตั้งใจไว้
เรามาลองคิดดูว่าเกิดอะไรขึ้น arr
สามารถเป็นอาร์เรย์ของอะไรก็ได้ใช่ไหม? มันอาจมีตัวเลขหรือสตริงหรือวัตถุหรืออะไรก็ตาม เรามีชุด ของบางรายการ ในการจัดเรียง เราจำเป็นต้องมี ฟังก์ชันการเรียงลำดับ ที่รู้วิธีเปรียบเทียบองค์ประกอบต่างๆ ค่าเริ่มต้นคือลำดับสตริง
วิธี arr.sort(fn)
ใช้อัลกอริธึมการเรียงลำดับทั่วไป เราไม่จำเป็นต้องสนใจว่ามันทำงานอย่างไรภายใน (โดยส่วนใหญ่แล้ว Quicksort หรือ Timsort ที่ได้รับการปรับปรุง) มันจะเดินอาร์เรย์ เปรียบเทียบองค์ประกอบโดยใช้ฟังก์ชันที่ให้มา และเรียงลำดับใหม่ ทั้งหมดที่เราต้องการคือระบุ fn
ที่จะทำการเปรียบเทียบ
อย่างไรก็ตาม หากเราต้องการทราบว่าองค์ประกอบใดที่ถูกเปรียบเทียบ ไม่มีอะไรขัดขวางไม่ให้เราแจ้งเตือน:
[1, -2, 15, 2, 0, 8].sort(ฟังก์ชัน(a, b) { การแจ้งเตือน ( a + " <> " + b ); ส่งคืน a - b; -
อัลกอริทึมอาจเปรียบเทียบองค์ประกอบกับองค์ประกอบอื่นๆ หลายรายการในกระบวนการ แต่จะพยายามทำการเปรียบเทียบให้น้อยที่สุดเท่าที่จะเป็นไปได้
ฟังก์ชันการเปรียบเทียบอาจส่งคืนตัวเลขใดๆ ก็ได้
จริงๆ แล้ว ฟังก์ชันการเปรียบเทียบจำเป็นเพียงเพื่อส่งกลับจำนวนบวกที่บอกว่า "มากขึ้น" และจำนวนลบที่จะบอกว่า "น้อยลง"
ที่อนุญาตให้เขียนฟังก์ชันที่สั้นลง:
ให้ arr = [ 1, 2, 15 ]; arr.sort(ฟังก์ชั่น(a, b) { กลับ a - b; }); การแจ้งเตือน(arr); // 1, 2, 15
ฟังก์ชั่นลูกศรเพื่อสิ่งที่ดีที่สุด
จำฟังก์ชั่นลูกศรได้ไหม? เราสามารถใช้มันที่นี่เพื่อการเรียงลำดับที่ประณีตยิ่งขึ้น:
arr.sort( (ก, ข) => ก - ข );
การทำงานนี้เหมือนกับเวอร์ชันที่ยาวกว่าด้านบนทุกประการ
ใช้ localeCompare
สำหรับสตริง
จำอัลกอริธึมการเปรียบเทียบสตริงได้ไหม โดยจะเปรียบเทียบตัวอักษรด้วยรหัสตามค่าเริ่มต้น
สำหรับตัวอักษรหลายๆ ตัว ควรใช้วิธี str.localeCompare
เพื่อจัดเรียงตัวอักษรให้ถูกต้อง เช่น Ö
ตัวอย่างเช่น ลองจัดเรียงบางประเทศเป็นภาษาเยอรมัน:
ให้ประเทศ = ['Österreich', 'อันดอร์รา', 'เวียดนาม']; การแจ้งเตือน(country.sort( (a, b) => a > b ? 1 : -1) ); // อันดอร์รา เวียดนาม เอิสเตอร์ไรช์ (ผิด) การแจ้งเตือน (country.sort( (a, b) => a.localeCompare(b) ) ); // อันดอร์รา,เอิสเตอร์ไรช์,เวียดนาม (ถูกต้อง!)
วิธีการ arr.reverse กลับลำดับขององค์ประกอบใน arr
ตัวอย่างเช่น:
ให้ arr = [1, 2, 3, 4, 5]; arr.ย้อนกลับ(); แจ้งเตือน(arr); // 5,4,3,2,1
นอกจากนี้ยังส่งคืนอาร์เรย์ arr
หลังจากการกลับรายการอีกด้วย
นี่คือสถานการณ์จากชีวิตจริง เรากำลังเขียนแอปส่งข้อความ และบุคคลนั้นเข้าสู่รายชื่อผู้รับที่คั่นด้วยเครื่องหมายจุลภาค: John, Pete, Mary
. แต่สำหรับเราแล้ว อาร์เรย์ของชื่อจะสะดวกกว่าสตริงเดี่ยวมาก จะได้รับมันได้อย่างไร?
เมธอด str.split(delim) ทำสิ่งนั้นทุกประการ มันแยกสตริงออกเป็นอาร์เรย์ด้วยตัวคั่นที่กำหนด delim
ในตัวอย่างด้านล่าง เราแบ่งด้วยเครื่องหมายจุลภาคตามด้วยช่องว่าง:
ให้ชื่อ = 'บิลโบ, แกนดัล์ฟ, นัซกุล'; ให้ arr = name.split(', '); สำหรับ (ให้ชื่อของ arr) { alert( `ข้อความถึง ${name}.` ); // ข้อความถึงบิลโบ (และชื่ออื่นๆ) -
วิธี split
มีอาร์กิวเมนต์ตัวเลขตัวเลือกที่สอง ซึ่งเป็นขีดจำกัดความยาวของอาร์เรย์ หากมีการระบุไว้ องค์ประกอบพิเศษจะถูกละเว้น ในทางปฏิบัติไม่ค่อยมีการใช้:
ให้ arr = 'บิลโบ, แกนดัล์ฟ, นาซกุล, ซารูมาน'.split(', ', 2); การแจ้งเตือน(arr); // บิลโบ, แกนดัล์ฟ
แยกออกเป็นตัวอักษร
การเรียกร้องให้ split(s)
ด้วยช่องว่าง s
จะแยกสตริงออกเป็นอาร์เรย์ของตัวอักษร:
ให้ str = "ทดสอบ"; alert( str.split('') ); // ทดสอบ
การโทร arr.join(glue) ทำการย้อนกลับเพื่อ split
มันสร้างสตริงของรายการ arr
ที่เชื่อมต่อกันด้วย glue
ระหว่างรายการเหล่านั้น
ตัวอย่างเช่น:
ให้ arr = ['บิลโบ', 'แกนดัล์ฟ', 'นาซกุล']; ให้ str = arr.join(';'); // ติดอาร์เรย์เข้ากับสตริงโดยใช้ ; การแจ้งเตือน (str); // บิลโบ;แกนดัล์ฟ;นาซกุล
เมื่อเราต้องการวนซ้ำอาร์เรย์ เราสามารถใช้ forEach
, for
หรือ for..of
เมื่อเราต้องการวนซ้ำและส่งคืนข้อมูลสำหรับแต่ละองค์ประกอบ เราสามารถใช้ map
เมธอด arr.reduce และ arr.reduceRight ก็เป็นของสายพันธุ์นั้นเช่นกัน แต่จะซับซ้อนกว่าเล็กน้อย ใช้ในการคำนวณค่าเดียวตามอาร์เรย์
ไวยากรณ์คือ:
ให้ค่า = arr.reduce (ฟังก์ชั่น (ตัวสะสม, รายการ, ดัชนี, อาร์เรย์) { - }, [อักษรย่อ]);
ฟังก์ชันนี้ใช้กับองค์ประกอบอาร์เรย์ทั้งหมดทีละรายการและ "ดำเนินการต่อ" ผลลัพธ์ในการเรียกครั้งถัดไป
ข้อโต้แย้ง:
accumulator
– คือผลลัพธ์ของการเรียกใช้ฟังก์ชันก่อนหน้า ซึ่งเท่ากับ initial
ในครั้งแรก (หากระบุ initial
ไว้)
item
– คือรายการอาร์เรย์ปัจจุบัน
index
– คือตำแหน่งของมัน
array
- คืออาร์เรย์
เมื่อมีการใช้ฟังก์ชัน ผลลัพธ์ของการเรียกใช้ฟังก์ชันก่อนหน้าจะถูกส่งผ่านไปยังอาร์กิวเมนต์แรกไปยังอาร์กิวเมนต์แรก
ดังนั้น อาร์กิวเมนต์แรกคือตัวสะสมที่เก็บผลลัพธ์รวมของการดำเนินการก่อนหน้านี้ทั้งหมด และสุดท้ายก็กลายเป็นผลจาก reduce
ฟังดูซับซ้อนใช่ไหม?
วิธีที่ง่ายที่สุดที่จะเข้าใจสิ่งนั้นก็คือการเป็นตัวอย่าง
ที่นี่เราได้รับผลรวมของอาร์เรย์ในหนึ่งบรรทัด:
ให้ arr = [1, 2, 3, 4, 5]; ให้ result = arr.reduce((sum, current) => sum + current, 0); การแจ้งเตือน (ผลลัพธ์); // 15
ฟังก์ชันที่ส่งเพื่อ reduce
ใช้เพียง 2 อาร์กิวเมนต์ ซึ่งโดยทั่วไปก็เพียงพอแล้ว
เรามาดูรายละเอียดกันว่ามีอะไรบ้าง
ในการรันครั้งแรก sum
คือค่า initial
(อาร์กิวเมนต์สุดท้ายของ reduce
) เท่ากับ 0
และ current
เป็นองค์ประกอบอาร์เรย์แรก เท่ากับ 1
ดังนั้นผลลัพธ์ของฟังก์ชันคือ 1
ในการรันครั้งที่สอง sum = 1
เราจะเพิ่มองค์ประกอบอาร์เรย์ที่สอง ( 2
) เข้าไปและส่งคืน
ในการรันครั้งที่ 3 sum = 3
และเราเพิ่มองค์ประกอบอีกหนึ่งรายการเข้าไป และต่อๆ ไป...
ขั้นตอนการคำนวณ:
หรือในรูปแบบของตาราง โดยแต่ละแถวแสดงถึงการเรียกใช้ฟังก์ชันในองค์ประกอบอาร์เรย์ถัดไป:
sum | current | ผลลัพธ์ | |
---|---|---|---|
การโทรครั้งแรก | 0 | 1 | 1 |
การโทรครั้งที่สอง | 1 | 2 | 3 |
การโทรครั้งที่สาม | 3 | 3 | 6 |
การโทรครั้งที่สี่ | 6 | 4 | 10 |
การโทรครั้งที่ห้า | 10 | 5 | 15 |
ที่นี่เราจะเห็นได้อย่างชัดเจนว่าผลลัพธ์ของการโทรครั้งก่อนกลายเป็นอาร์กิวเมนต์แรกของการโทรครั้งถัดไปอย่างไร
นอกจากนี้เรายังสามารถละเว้นค่าเริ่มต้นได้:
ให้ arr = [1, 2, 3, 4, 5]; // ลบค่าเริ่มต้นออกจากการลด (หมายเลข 0) ให้ result = arr.reduce((sum, current) => sum + current); การแจ้งเตือน (ผลลัพธ์); // 15
ผลลัพธ์ก็เหมือนกัน นั่นเป็นเพราะว่าหากไม่มีค่าเริ่มต้น ดังนั้น reduce
จะใช้องค์ประกอบแรกของอาร์เรย์เป็นค่าเริ่มต้น และเริ่มการวนซ้ำจากองค์ประกอบที่ 2
ตารางการคำนวณเหมือนกับด้านบน ลบแถวแรก
แต่การใช้งานดังกล่าวต้องได้รับการดูแลเป็นพิเศษ หากอาร์เรย์ว่างเปล่า reduce
การเรียกโดยไม่มีค่าเริ่มต้นจะทำให้เกิดข้อผิดพลาด
นี่คือตัวอย่าง:
ให้ arr = []; // ข้อผิดพลาด: ลดอาร์เรย์ว่างที่ไม่มีค่าเริ่มต้น // หากมีค่าเริ่มต้นอยู่ ลด จะส่งคืนค่านั้นสำหรับค่า arr ว่าง arr.reduce((ผลรวม, ปัจจุบัน) => ผลรวม + ปัจจุบัน);
ดังนั้นจึงแนะนำให้ระบุค่าเริ่มต้นเสมอ
วิธีการ arr.reduceRight ทำเช่นเดียวกันแต่เปลี่ยนจากขวาไปซ้าย
อาร์เรย์ไม่สร้างประเภทภาษาแยกต่างหาก พวกมันขึ้นอยู่กับวัตถุ
ดังนั้น typeof
จึงไม่ช่วยแยกแยะวัตถุธรรมดาจากอาร์เรย์:
การแจ้งเตือน (ประเภทของ {}); // วัตถุ การแจ้งเตือน (ประเภทของ []); // วัตถุ (เหมือนกัน)
…แต่มีการใช้อาร์เรย์บ่อยมากจนมีวิธีการพิเศษสำหรับสิ่งนั้น: Array.isArray(value) หาก value
เป็นอาร์เรย์ จะส่งคืนค่า true
หากเป็นอาร์เรย์ false
ฉะนั้นจะคืนค่าเป็นเท็จ
การแจ้งเตือน (Array.isArray({})); // เท็จ การแจ้งเตือน (Array.isArray([])); // จริง
เมธอดอาร์เรย์เกือบทั้งหมดที่เรียกใช้ฟังก์ชัน เช่น find
, filter
, map
โดยมีข้อยกเว้นที่โดดเด่นคือ sort
จะยอมรับพารามิเตอร์เพิ่มเติมที่เป็นทางเลือก thisArg
พารามิเตอร์นั้นไม่ได้อธิบายไว้ในส่วนด้านบน เนื่องจากไม่ค่อยได้ใช้ แต่เพื่อความสมบูรณ์เราก็ต้องปกปิดไว้
ต่อไปนี้คือไวยากรณ์ทั้งหมดของวิธีการเหล่านี้:
arr.find(func, thisArg); arr.filter(func, thisArg); arr.map(func, thisArg); - // thisArg เป็นอาร์กิวเมนต์สุดท้ายที่เป็นทางเลือก
ค่าของพารามิเตอร์ thisArg
จะกลายเป็น this
สำหรับ func
ตัวอย่างเช่น ที่นี่เราใช้วิธีของ army
object เป็นตัวกรอง และ thisArg
จะส่งผ่านบริบท:
ให้กองทัพ = { อายุขั้นต่ำ: 18, อายุสูงสุด: 27, สามารถเข้าร่วม (ผู้ใช้) { ส่งคืน user.age >= this.minAge && user.age < this.maxAge; - - ให้ผู้ใช้ = [ {อายุ: 16}, {อายุ: 20}, {อายุ: 23}, {อายุ: 30} - // ค้นหาผู้ใช้ สำหรับผู้ที่ army.canJoin ส่งคืนค่าจริง ให้ทหาร = users.filter(army.canJoin, army); การแจ้งเตือน (ทหารความยาว); // 2 การแจ้งเตือน(ทหาร[0].อายุ); // 20 การแจ้งเตือน(ทหาร[1].อายุ); // 23
หากในตัวอย่างข้างต้น เราใช้ users.filter(army.canJoin)
ดังนั้น army.canJoin
จะถูกเรียกว่าเป็นฟังก์ชันแบบสแตนด์อโลน โดยมี this=undefined
ทำให้เกิดข้อผิดพลาดทันที
การเรียก users.filter(army.canJoin, army)
สามารถแทนที่ได้ด้วย users.filter(user => army.canJoin(user))
ซึ่งทำเช่นเดียวกัน อย่างหลังนี้ใช้บ่อยกว่าเพราะคนส่วนใหญ่จะเข้าใจง่ายกว่าเล็กน้อย
แผ่นโกงของวิธีการอาร์เรย์:
ในการเพิ่ม/ลบองค์ประกอบ:
push(...items)
– เพิ่มรายการต่อท้าย
pop()
– แยกรายการออกจากส่วนท้าย
shift()
– แยกรายการจากจุดเริ่มต้น
unshift(...items)
– เพิ่มรายการไปที่จุดเริ่มต้น
splice(pos, deleteCount, ...items)
– ที่ดัชนี pos
จะลบองค์ประกอบ deleteCount
และแทรก items
slice(start, end)
– สร้างอาร์เรย์ใหม่ คัดลอกองค์ประกอบตั้งแต่ start
จนถึง end
ดัชนี (ไม่รวม) ลงไป
concat(...items)
– ส่งคืนอาร์เรย์ใหม่: คัดลอกสมาชิกทั้งหมดของอาร์เรย์ปัจจุบันและเพิ่ม items
เข้าไป หากมี items
ใดเป็นอาร์เรย์ องค์ประกอบนั้นจะถูกนำมาใช้
หากต้องการค้นหาระหว่างองค์ประกอบ:
indexOf/lastIndexOf(item, pos)
– ค้นหา item
ที่เริ่มต้นจากตำแหน่ง pos
และส่งคืนดัชนีหรือ -1
หากไม่พบ
includes(value)
– คืนค่า true
หากอาร์เรย์มี value
มิฉะนั้นจะคืนค่า false
find/filter(func)
– กรององค์ประกอบผ่านฟังก์ชัน ส่งกลับค่าแรก/ทั้งหมดที่ทำให้มันส่งกลับ true
findIndex
เหมือนกับ find
แต่ส่งคืนดัชนีแทนที่จะเป็นค่า
หากต้องการวนซ้ำองค์ประกอบ:
forEach(func)
– เรียกใช้ func
สำหรับทุกองค์ประกอบ โดยจะไม่ส่งคืนสิ่งใดเลย
ในการแปลงอาร์เรย์:
map(func)
– สร้างอาร์เรย์ใหม่จากผลลัพธ์การเรียก func
สำหรับทุกองค์ประกอบ
sort(func)
– เรียงลำดับอาร์เรย์ในตำแหน่งแล้วส่งคืน
reverse()
– กลับอาร์เรย์ในตำแหน่งเดิมแล้วส่งคืน
split/join
– แปลงสตริงเป็นอาร์เรย์และย้อนกลับ
reduce/reduceRight(func, initial)
– คำนวณค่าเดียวบนอาร์เรย์โดยการเรียก func
สำหรับแต่ละองค์ประกอบและส่งผลลัพธ์ระดับกลางระหว่างการโทร
นอกจากนี้:
Array.isArray(value)
ตรวจสอบ value
สำหรับการเป็นอาร์เรย์ หากเป็นเช่นนั้นจะส่งกลับค่า true
มิฉะนั้นจะคืนค่า false
โปรดทราบว่าวิธี sort
, reverse
และ splice
จะปรับเปลี่ยนอาร์เรย์เอง
วิธีการเหล่านี้เป็นวิธีการที่ใช้มากที่สุด โดยครอบคลุม 99% ของกรณีการใช้งาน แต่มีอีกไม่กี่อย่าง:
arr.some(fn)/arr.every(fn) ตรวจสอบอาร์เรย์
ฟังก์ชัน fn
ถูกเรียกใช้ในแต่ละองค์ประกอบของอาร์เรย์ที่คล้ายกับ map
หากผลลัพธ์ใดๆ/ทั้งหมดเป็น true
จะส่งกลับค่า true
มิฉะนั้นจะเป็น false
วิธีการเหล่านี้มีพฤติกรรมเหมือน ||
และตัวดำเนินการ &&
: หาก fn
ส่งกลับค่าความจริง arr.some()
จะส่งคืน true
ทันทีและหยุดวนซ้ำกับรายการที่เหลือ หาก fn
ส่งกลับค่าเท็จ arr.every()
จะส่งคืน false
ทันทีและหยุดการวนซ้ำกับรายการที่เหลือเช่นกัน
เราสามารถใช้ every
เพื่อเปรียบเทียบอาร์เรย์:
ฟังก์ชั่น arraysEqual (arr1, arr2) { ส่งคืน arr1.length === arr2.length && arr1.every ((ค่า, ดัชนี) => ค่า === arr2 [ดัชนี]); - การแจ้งเตือน ( arraysEqual ([1, 2], [1, 2])); // จริง
arr.fill(value, start, end) – เติมอาร์เรย์ด้วย value
ซ้ำตั้งแต่ start
จน end
ดัชนี
arr.copyWithin(target, start, end) – คัดลอกองค์ประกอบจากตำแหน่ง start
จนถึงตำแหน่ง end
ใน ตัวมันเอง ที่ตำแหน่ง target
(เขียนทับที่มีอยู่)
arr.flat(ความลึก)/arr.flatMap(fn) สร้างอาร์เรย์แบบแบนใหม่จากอาร์เรย์หลายมิติ
สำหรับรายการทั้งหมด โปรดดูคู่มือ
เมื่อแรกเห็นอาจดูเหมือนมีวิธีการมากมายจนน่าจดจำค่อนข้างยาก แต่จริงๆ แล้ว มันง่ายกว่ามาก
ดูเอกสารโกงเพียงเพื่อให้ทราบ แล้วแก้งานในบทนี้เพื่อฝึกฝนเพื่อให้คุณมีประสบการณ์กับวิธีการอาร์เรย์
หลังจากนั้นเมื่อใดก็ตามที่คุณต้องการทำอะไรบางอย่างกับอาร์เรย์ และคุณไม่รู้ว่าต้องทำอย่างไร มาที่นี่ เพื่อดูสูตรโกงและค้นหาวิธีที่ถูกต้อง ตัวอย่างจะช่วยให้คุณเขียนได้อย่างถูกต้อง ในไม่ช้าคุณจะจดจำวิธีการต่าง ๆ โดยอัตโนมัติ โดยไม่ต้องพยายามเป็นพิเศษจากคุณ
ความสำคัญ: 5
เขียนฟังก์ชัน camelize(str)
ที่เปลี่ยนคำที่คั่นด้วยเส้นประ เช่น “my-short-string” ให้เป็น “myShortString” ที่ใส่อูฐ
นั่นคือ: ลบขีดกลางทั้งหมด แต่ละคำหลังขีดจะกลายเป็นตัวพิมพ์ใหญ่
ตัวอย่าง:
Camelize("สีพื้นหลัง") == 'สีพื้นหลัง'; Camelize("list-style-image") == 'listStyleImage'; Camelize("-webkit-transition") == 'WebkitTransition';
PS คำแนะนำ: ใช้ split
เพื่อแยกสตริงออกเป็นอาร์เรย์ แปลงสตริงแล้ว join
กลับ
เปิดแซนด์บ็อกซ์พร้อมการทดสอบ
ฟังก์ชั่นอูฐ (str) { ถนนกลับ .split('-') // แยก 'my-long-word' ออกเป็นอาร์เรย์ ['my', 'long', 'word'] .แผนที่( // ใช้อักษรตัวแรกของรายการอาร์เรย์ทั้งหมดเป็นตัวพิมพ์ใหญ่ ยกเว้นตัวแรก // แปลง ['ของฉัน', 'ยาว', 'คำ'] เป็น ['ของฉัน', 'ยาว', 'Word'] (คำ, ดัชนี) => ดัชนี == 0 ? คำ : คำ[0].toUpperCase() + word.slice(1) - .เข้าร่วม(''); // รวม ['my', 'Long', 'Word'] ลงใน 'myLongWord' -
เปิดโซลูชันพร้อมการทดสอบในแซนด์บ็อกซ์
ความสำคัญ: 4
เขียนฟังก์ชัน filterRange(arr, a, b)
ที่ได้รับอาร์เรย์ arr
ค้นหาองค์ประกอบที่มีค่าสูงกว่าหรือเท่ากับ a
และต่ำกว่าหรือเท่ากับ b
แล้วส่งคืนผลลัพธ์เป็นอาร์เรย์
ฟังก์ชันไม่ควรแก้ไขอาร์เรย์ ควรส่งคืนอาร์เรย์ใหม่
ตัวอย่างเช่น:
ให้ arr = [5, 3, 8, 1]; ให้กรอง = filterRange (arr, 1, 4); การแจ้งเตือน (กรองแล้ว); // 3,1 (ค่าที่ตรงกัน) แจ้งเตือน(arr); // 5,3,8,1 (ไม่แก้ไข)
เปิดแซนด์บ็อกซ์พร้อมการทดสอบ
ฟังก์ชั่น filterRange (arr, a, b) { // เพิ่มวงเล็บรอบนิพจน์เพื่อให้อ่านง่ายขึ้น กลับ arr.filter(item => (a <= item && item <= b)); - ให้ arr = [5, 3, 8, 1]; ให้กรอง = filterRange (arr, 1, 4); การแจ้งเตือน (กรองแล้ว); // 3,1 (ค่าที่ตรงกัน) แจ้งเตือน(arr); // 5,3,8,1 (ไม่แก้ไข)
เปิดโซลูชันพร้อมการทดสอบในแซนด์บ็อกซ์
ความสำคัญ: 4
เขียนฟังก์ชัน filterRangeInPlace(arr, a, b)
ที่ได้รับอาร์เรย์ arr
และลบค่าทั้งหมดออกจากมัน ยกเว้นค่าที่อยู่ระหว่าง a
และ b
การทดสอบคือ: a ≤ arr[i] ≤ b
ฟังก์ชันควรแก้ไขอาร์เรย์เท่านั้น ไม่ควรคืนสิ่งใด
ตัวอย่างเช่น:
ให้ arr = [5, 3, 8, 1]; filterRangeInPlace (arr, 1, 4); // ลบตัวเลขยกเว้น 1 ถึง 4 แจ้งเตือน(arr); // [3, 1]
เปิดแซนด์บ็อกซ์พร้อมการทดสอบ
ฟังก์ชั่น filterRangeInPlace (arr, a, b) { สำหรับ (ให้ i = 0; i < arr.length; i++) { ให้วาล = arr[i]; // ลบออกหากอยู่นอกช่วงเวลา ถ้า (val < a || val > b) { arr.splice(i, 1); ฉัน--; - - - ให้ arr = [5, 3, 8, 1]; filterRangeInPlace (arr, 1, 4); // ลบตัวเลขยกเว้น 1 ถึง 4 แจ้งเตือน(arr); // [3, 1]
เปิดโซลูชันพร้อมการทดสอบในแซนด์บ็อกซ์
ความสำคัญ: 4
ให้ arr = [5, 2, 1, -10, 8]; // ... รหัสของคุณเพื่อเรียงลำดับจากลดลง แจ้งเตือน(arr); // 8, 5, 2, 1, -10
ให้ arr = [5, 2, 1, -10, 8]; arr.sort((ก, ข) => ข - ก); แจ้งเตือน(arr);
ความสำคัญ: 5
เรามีอาร์เรย์ของสตริง arr
เราต้องการมีสำเนาที่จัดเรียงไว้ แต่ arr
การแก้ไขใดๆ
สร้างฟังก์ชัน copySorted(arr)
ที่ส่งคืนสำเนาดังกล่าว
ให้ arr = ["HTML", "JavaScript", "CSS"]; ให้ sorted = copySorted (arr); การแจ้งเตือน ( เรียงลำดับ ); // CSS, HTML, จาวาสคริปต์ แจ้งเตือน(arr); // HTML, JavaScript, CSS (ไม่มีการเปลี่ยนแปลง)
เราสามารถใช้ slice()
เพื่อทำสำเนาและเรียกใช้การเรียงลำดับ:
ฟังก์ชั่น copySorted (arr) { กลับ arr.slice().sort(); - ให้ arr = ["HTML", "JavaScript", "CSS"]; ให้ sorted = copySorted (arr); การแจ้งเตือน ( เรียงลำดับ ); แจ้งเตือน(arr);
ความสำคัญ: 5
สร้างฟังก์ชันตัวสร้าง Calculator
ที่สร้างวัตถุเครื่องคิดเลข "ขยายได้"
งานประกอบด้วยสองส่วน
ขั้นแรก ใช้วิธี calculate(str)
ซึ่งรับสตริง เช่น "1 + 2"
ในรูปแบบ “ตัวดำเนินการ NUMBER NUMBER” (คั่นด้วยช่องว่าง) และส่งกลับผลลัพธ์ ควรเข้าใจบวก +
และลบ -
ตัวอย่างการใช้งาน:
ให้ calc = เครื่องคิดเลขใหม่; การแจ้งเตือน( calc.calculate("3 + 7") ); // 10
จากนั้นเพิ่มเมธอด addMethod(name, func)
ที่สอนเครื่องคิดเลขถึงการดำเนินการใหม่ ใช้ name
ตัวดำเนินการและฟังก์ชันสองอาร์กิวเมนต์ func(a,b)
ที่นำไปใช้
ตัวอย่างเช่น ลองบวกการคูณ *
, การหาร /
และกำลัง **
:
ให้ powerCalc = เครื่องคิดเลขใหม่; powerCalc.addMethod("*", (a, b) => a * b); powerCalc.addMethod("/", (a, b) => a / b); powerCalc.addMethod("**", (a, b) => a ** b); ให้ result = powerCalc.calculate("2 ** 3"); การแจ้งเตือน (ผลลัพธ์); // 8
ไม่มีวงเล็บหรือนิพจน์ที่ซับซ้อนในงานนี้
ตัวเลขและตัวดำเนินการจะถูกคั่นด้วยช่องว่างเดียว
อาจมีการจัดการข้อผิดพลาดหากคุณต้องการเพิ่ม
เปิดแซนด์บ็อกซ์พร้อมการทดสอบ
โปรดทราบว่าวิธีการจัดเก็บ พวกเขาจะถูกเพิ่มเข้าไปในคุณสมบัติ this.methods
การทดสอบและการแปลงตัวเลขทั้งหมดดำเนินการด้วยวิธี calculate
ในอนาคตอาจมีการขยายเพื่อรองรับนิพจน์ที่ซับซ้อนมากขึ้น
ฟังก์ชั่นเครื่องคิดเลข() { นี้.methods = { "-": (ก, ข) => ก - ข, "+": (ก, ข) => ก + ข - this.calculate = ฟังก์ชั่น (str) { ให้ split = str.split(' '), ก = +แยก[0], สหกรณ์ = แยก[1], ข = +แยก[2]; ถ้า (!this.methods[op] || isNaN(a) || isNaN(b)) { กลับน่าน; - กลับ this.methods[op](a, b); - this.addMethod = ฟังก์ชั่น (ชื่อ func) { this.methods[ชื่อ] = func; - -
เปิดโซลูชันพร้อมการทดสอบในแซนด์บ็อกซ์
ความสำคัญ: 5
คุณมีอาร์เรย์ของออบเจ็กต์ user
โดยแต่ละออบเจ็กต์มี user.name
เขียนโค้ดที่จะแปลงเป็นอาร์เรย์ของชื่อ
ตัวอย่างเช่น:
ให้จอห์น = { ชื่อ: "จอห์น" อายุ: 25 }; ให้พีท = { ชื่อ: "พีท" อายุ: 30 }; ให้แมรี่ = { ชื่อ: "แมรี่" อายุ: 28 }; ให้ผู้ใช้ = [ จอห์น, พีท, แมรี่ ]; ให้ชื่อ = /* ... รหัสของคุณ */ การแจ้งเตือน (ชื่อ); // จอห์น พีท แมรี่
ให้จอห์น = { ชื่อ: "จอห์น" อายุ: 25 }; ให้พีท = { ชื่อ: "พีท" อายุ: 30 }; ให้แมรี่ = { ชื่อ: "แมรี่" อายุ: 28 }; ให้ผู้ใช้ = [ จอห์น, พีท, แมรี่ ]; ให้ชื่อ = users.map(item => item.name); การแจ้งเตือน (ชื่อ); // จอห์น พีท แมรี่
ความสำคัญ: 5
คุณมีอาร์เรย์ของออบเจ็กต์ user
โดยแต่ละออบเจ็กต์มี name
surname
และ id
เขียนโค้ดเพื่อสร้างอาร์เรย์อื่นจากนั้น ของวัตถุที่มี id
และ fullName
โดยที่ fullName
ถูกสร้างขึ้นจาก name
และ surname
ตัวอย่างเช่น:
ให้จอห์น = { ชื่อ: "จอห์น", นามสกุล: "สมิ ธ", id: 1 }; ให้พีท = { ชื่อ: "พีท", นามสกุล: "ล่า", id: 2 }; ให้ mary = { ชื่อ: "แมรี่" นามสกุล: "คีย์", id: 3 }; ให้ผู้ใช้ = [ จอห์น, พีท, แมรี่ ]; ให้ usersMapped = /* ... รหัสของคุณ ... */ - usersMapped = [ { ชื่อเต็ม: "จอห์น สมิธ", รหัส: 1 }, { ชื่อเต็ม: "พีท ฮันท์", id: 2 }, { ชื่อเต็ม: "แมรี่คีย์", รหัส: 3 } - - การแจ้งเตือน ( usersMapped[0].id ) // 1 การแจ้งเตือน ( usersMapped [0] .fullName ) // John Smith
ดังนั้น จริงๆ แล้ว คุณจำเป็นต้องแมปอาร์เรย์ของวัตถุหนึ่งไปยังอีกอาร์เรย์หนึ่ง ลองใช้ =>
ที่นี่ มีการจับเล็กน้อย
ให้จอห์น = { ชื่อ: "จอห์น", นามสกุล: "สมิ ธ", id: 1 }; ให้พีท = { ชื่อ: "พีท", นามสกุล: "ล่า", id: 2 }; ให้ mary = { ชื่อ: "แมรี่" นามสกุล: "คีย์", id: 3 }; ให้ผู้ใช้ = [ จอห์น, พีท, แมรี่ ]; ให้ usersMapped = users.map(user => ({ ชื่อเต็ม: `${user.name} ${user.surname}`, รหัส: user.id - - usersMapped = [ { ชื่อเต็ม: "จอห์น สมิธ", รหัส: 1 }, { ชื่อเต็ม: "พีท ฮันท์", id: 2 }, { ชื่อเต็ม: "แมรี่คีย์", รหัส: 3 } - - การแจ้งเตือน ( usersMapped[0].id ); // 1 การแจ้งเตือน ( usersMapped[0].fullName ); // จอห์น สมิธ
โปรดทราบว่าในฟังก์ชันลูกศรเราจำเป็นต้องใช้วงเล็บเพิ่มเติม
เราไม่สามารถเขียนแบบนี้:
ให้ usersMapped = users.map(user => { ชื่อเต็ม: `${user.name} ${user.surname}`, รหัส: user.id -
อย่างที่เราจำได้ มีฟังก์ชันลูกศรอยู่สองฟังก์ชัน: ไม่มี body value => expr
และด้วย body value => {...}
ในที่นี้ JavaScript จะถือว่า {
เป็นจุดเริ่มต้นของเนื้อหาของฟังก์ชัน ไม่ใช่จุดเริ่มต้นของอ็อบเจ็กต์ วิธีแก้ปัญหาคือล้อมไว้ในวงเล็บ "ปกติ":
ให้ usersMapped = users.map(user => ({ ชื่อเต็ม: `${user.name} ${user.surname}`, รหัส: user.id -
ตอนนี้สบายดี
ความสำคัญ: 5
เขียนฟังก์ชัน sortByAge(users)
ที่ได้รับอาร์เรย์ของอ็อบเจ็กต์ที่มีคุณสมบัติ age
และจัดเรียงตาม age
ตัวอย่างเช่น:
ให้จอห์น = { ชื่อ: "จอห์น" อายุ: 25 }; ให้พีท = { ชื่อ: "พีท" อายุ: 30 }; ให้แมรี่ = { ชื่อ: "แมรี่" อายุ: 28 }; ให้ arr = [ พีท, จอห์น, แมรี่ ]; sortByAge(arr); // ตอนนี้: [จอห์น แมรี่ พีท] การแจ้งเตือน (arr[0].ชื่อ); // จอห์น การแจ้งเตือน(arr[1].ชื่อ); //แมรี่ การแจ้งเตือน (arr [2] .name); //พีท
ฟังก์ชั่น sortByAge (arr) { arr.sort((a, b) => a.age - b.age); - ให้จอห์น = { ชื่อ: "จอห์น" อายุ: 25 }; ให้พีท = { ชื่อ: "พีท" อายุ: 30 }; ให้แมรี่ = { ชื่อ: "แมรี่" อายุ: 28 }; ให้ arr = [ พีท, จอห์น, แมรี่ ]; sortByAge(arr); // ตอนนี้เรียงลำดับแล้ว: [john, mary, pete] การแจ้งเตือน (arr[0].ชื่อ); // จอห์น การแจ้งเตือน(arr[1].ชื่อ); //แมรี่ การแจ้งเตือน (arr [2] .name); //พีท
ความสำคัญ: 3
เขียนฟังก์ชัน shuffle(array)
ที่สับเปลี่ยน (เรียงลำดับแบบสุ่ม) องค์ประกอบของอาร์เรย์
การ shuffle
หลายครั้งอาจทำให้ลำดับขององค์ประกอบต่างกัน ตัวอย่างเช่น:
ให้ arr = [1, 2, 3]; สุ่ม(arr); // arr = [3, 2, 1] สุ่ม(arr); // arr = [2, 1, 3] สุ่ม(arr); // arr = [3, 1, 2] -
ลำดับองค์ประกอบทั้งหมดควรมีความน่าจะเป็นเท่ากัน ตัวอย่างเช่น [1,2,3]
สามารถเรียงลำดับใหม่เป็น [1,2,3]
หรือ [1,3,2]
หรือ [3,1,2]
เป็นต้น โดยมีความน่าจะเป็นเท่ากันในแต่ละกรณี
วิธีแก้ปัญหาง่ายๆ อาจเป็นดังนี้:
ฟังก์ชั่นสับเปลี่ยน (อาร์เรย์) { array.sort(() => คณิตสุ่ม() - 0.5); - ให้ arr = [1, 2, 3]; สุ่ม(arr); การแจ้งเตือน(arr);
ซึ่งค่อนข้างได้ผล เนื่องจาก Math.random() - 0.5
เป็นตัวเลขสุ่มที่อาจเป็นบวกหรือลบ ดังนั้นฟังก์ชันการเรียงลำดับจึงจัดลำดับองค์ประกอบใหม่แบบสุ่ม
แต่เนื่องจากฟังก์ชันการเรียงลำดับไม่ได้ตั้งใจจะใช้ในลักษณะนี้ การเรียงสับเปลี่ยนทั้งหมดจึงมีความน่าจะเป็นไม่เท่ากัน
ตัวอย่างเช่นพิจารณารหัสด้านล่าง มันทำงาน shuffle
10,000,000 เท่าและนับจำนวนผลการตรวจสอบทั้งหมดที่เป็นไปได้:
ฟังก์ชั่น Shuffle (อาร์เรย์) { array.sort (() => math.random () - 0.5); - // จำนวนการปรากฏตัวสำหรับการเปลี่ยนรูปแบบที่เป็นไปได้ทั้งหมด ให้ count = { '123': 0, '132': 0, '213': 0, '231': 0, '321': 0, '312': 0 - สำหรับ (ให้ i = 0; i <10,0000000; i ++) { ปล่อยให้อาร์เรย์ = [1, 2, 3]; Shuffle (อาร์เรย์); นับ [array.join ('')] ++; - // แสดงการนับจำนวนของการเรียงสับเปลี่ยนที่เป็นไปได้ทั้งหมด สำหรับ (ให้ปุ่มในการนับ) { การแจ้งเตือน (`$ {key}: $ {count [key]}`); -
ตัวอย่างผลลัพธ์ (ขึ้นอยู่กับเครื่องยนต์ JS):
123: 250706 132: 124425 213: 249618 231: 124880 312: 125148 321: 125223
เราสามารถเห็นอคติได้อย่างชัดเจน: 123
และ 213
ปรากฏบ่อยกว่าคนอื่น ๆ
ผลลัพธ์ของรหัสอาจแตกต่างกันระหว่างเครื่องยนต์ JavaScript แต่เราสามารถเห็นได้ว่าวิธีการนั้นไม่น่าเชื่อถือ
ทำไมมันไม่ทำงาน? โดยทั่วไปแล้ว sort
คือ "กล่องดำ": เราโยนอาร์เรย์และฟังก์ชั่นการเปรียบเทียบลงในนั้นและคาดว่าอาร์เรย์จะถูกจัดเรียง แต่เนื่องจากการสุ่มที่สุดของการเปรียบเทียบกล่องดำก็บ้าไปแล้วและวิธีที่มันบ้าขึ้นอยู่กับการใช้งานคอนกรีตที่แตกต่างระหว่างเครื่องยนต์
มีวิธีอื่น ๆ ที่ดีในการทำงาน ตัวอย่างเช่นมีอัลกอริทึมที่ดีที่เรียกว่า Fisher-Yates Shuffle แนวคิดคือการเดินอาร์เรย์ตามลำดับย้อนกลับและสลับแต่ละองค์ประกอบด้วยการสุ่มก่อน:
ฟังก์ชั่น Shuffle (อาร์เรย์) { สำหรับ (ให้ i = array.length-1; i> 0; i--) { ให้ j = math.floor (math.random () * (i + 1)); // ดัชนีสุ่มจาก 0 ถึง i // swap องค์ประกอบอาร์เรย์ [i] และอาร์เรย์ [j] // เราใช้ไวยากรณ์ "การทำลายโครงสร้าง" เพื่อให้บรรลุเป้าหมายนั้น // คุณจะพบรายละเอียดเพิ่มเติมเกี่ยวกับไวยากรณ์นั้นในบทต่อมา // เดียวกันสามารถเขียนเป็น: // ให้ t = อาร์เรย์ [i]; อาร์เรย์ [i] = อาร์เรย์ [j]; อาร์เรย์ [j] = t [Array [i], Array [J]] = [Array [J], Array [i]]; - -
ลองทดสอบด้วยวิธีเดียวกัน:
ฟังก์ชั่น Shuffle (อาร์เรย์) { สำหรับ (ให้ i = array.length-1; i> 0; i--) { ให้ j = math.floor (math.random () * (i + 1)); [Array [i], Array [J]] = [Array [J], Array [i]]; - - // จำนวนการปรากฏตัวสำหรับการเปลี่ยนรูปแบบที่เป็นไปได้ทั้งหมด ให้ count = { '123': 0, '132': 0, '213': 0, '231': 0, '321': 0, '312': 0 - สำหรับ (ให้ i = 0; i <10,0000000; i ++) { ปล่อยให้อาร์เรย์ = [1, 2, 3]; Shuffle (อาร์เรย์); นับ [array.join ('')] ++; - // แสดงการนับจำนวนของการเรียงสับเปลี่ยนที่เป็นไปได้ทั้งหมด สำหรับ (ให้ปุ่มในการนับ) { การแจ้งเตือน (`$ {key}: $ {count [key]}`); -
ตัวอย่างเอาต์พุต:
123: 166693 132: 166647 213: 166628 231: 167517 312: 166199 321: 166316
ตอนนี้ดูดี: การเรียงสับเปลี่ยนทั้งหมดปรากฏขึ้นพร้อมกับความน่าจะเป็นเหมือนกัน
ยิ่งไปกว่านั้นอัลกอริทึมของ Fisher-Yates ที่ดีกว่านั้นดีกว่ามากไม่มีค่าใช้จ่าย "การเรียงลำดับ"
ความสำคัญ: 4
เขียนฟังก์ชั่น getAverageAge(users)
ที่ได้รับอาร์เรย์ของวัตถุที่ age
อสังหาริมทรัพย์และส่งคืนอายุเฉลี่ย
สูตรสำหรับค่าเฉลี่ยคือ (age1 + age2 + ... + ageN) / N
ตัวอย่างเช่น:
ให้ John = {ชื่อ: "John", อายุ: 25}; ให้ pete = {ชื่อ: "pete", อายุ: 30}; ให้แมรี่ = {ชื่อ: "แมรี่", อายุ: 29}; ให้ arr = [John, Pete, Mary]; การแจ้งเตือน (getaverageage (arr)); // (25 + 30 + 29) / 3 = 28
ฟังก์ชั่น getaverageage (ผู้ใช้) { return users.reduce ((ก่อนหน้า, ผู้ใช้) => prev + user.age, 0) / users.length; - ให้ John = {ชื่อ: "John", อายุ: 25}; ให้ pete = {ชื่อ: "pete", อายุ: 30}; ให้แมรี่ = {ชื่อ: "แมรี่", อายุ: 29}; ให้ arr = [John, Pete, Mary]; การแจ้งเตือน (getaverageage (arr)); // 28
ความสำคัญ: 4
ให้ arr
เป็นอาร์เรย์
สร้างฟังก์ชั่น unique(arr)
ที่ควรส่งคืนอาร์เรย์ด้วยรายการที่ไม่ซ้ำกันของ arr
ตัวอย่างเช่น:
ฟังก์ชั่นที่ไม่ซ้ำกัน (arr) { / * รหัสของคุณ */ - ปล่อยให้สตริง = ["กระต่าย", "กฤษณะ", "กระต่าย", "กฤษณะ", "Krishna", "Krishna", "กระต่าย", "กระต่าย", ",": -o " - การแจ้งเตือน (ไม่ซ้ำกัน (strings)); // hare, krishna,: -o
เปิดแซนด์บ็อกซ์พร้อมการทดสอบ
มาเดินรายการอาร์เรย์กันเถอะ:
สำหรับแต่ละรายการเราจะตรวจสอบว่าอาร์เรย์ผลลัพธ์มีรายการนั้นอยู่แล้วหรือไม่
ถ้าเป็นเช่นนั้นให้ละเว้นมิฉะนั้นเพิ่มลงในผลลัพธ์
ฟังก์ชั่นที่ไม่ซ้ำกัน (arr) { ให้ผลลัพธ์ = []; สำหรับ (ให้ str ของ arr) { if (! result.includes (str)) { result.push (str); - - ส่งคืนผลลัพธ์; - ปล่อยให้สตริง = ["กระต่าย", "กฤษณะ", "กระต่าย", "กฤษณะ", "Krishna", "Krishna", "กระต่าย", "กระต่าย", ",": -o " - การแจ้งเตือน (ไม่ซ้ำกัน (strings)); // hare, krishna,: -o
รหัสใช้งานได้ แต่มีปัญหาด้านประสิทธิภาพที่อาจเกิดขึ้น
วิธี result.includes(str)
ภายในเดิน result
ของอาร์เรย์และเปรียบเทียบแต่ละองค์ประกอบกับ str
เพื่อค้นหาการจับคู่
ดังนั้นหากมี 100
องค์ประกอบใน result
และไม่มีใครตรงกับ str
มันจะเดินผ่าน result
ทั้งหมดและทำการเปรียบเทียบ 100
อย่างแน่นอน และถ้า result
มีขนาดใหญ่เช่น 10000
แล้วก็จะมีการเปรียบเทียบ 10000
นั่นไม่ใช่ปัญหาด้วยตัวเองเพราะเครื่องยนต์ JavaScript นั้นเร็วมากดังนั้นการเดิน 10000
อาเรย์จึงเป็นเรื่องของไมโครวินาที
แต่เราทำการทดสอบดังกล่าวสำหรับแต่ละองค์ประกอบของ arr
ใน for
รอบ
ดังนั้นหาก arr.length
คือ 10000
เราจะมีบางอย่างเช่น 10000*10000
= 100 ล้านของการเปรียบเทียบ นั่นเป็นจำนวนมาก
ดังนั้นการแก้ปัญหาจึงดีสำหรับอาร์เรย์ขนาดเล็กเท่านั้น
เพิ่มเติมในแผนที่บทและตั้งค่าเราจะดูวิธีการปรับให้เหมาะสม
เปิดโซลูชันพร้อมการทดสอบในแซนด์บ็อกซ์
ความสำคัญ: 4
สมมติว่าเราได้รับอาร์เรย์ของผู้ใช้ในแบบฟอร์ม {id:..., name:..., age:... }
สร้างฟังก์ชัน groupById(arr)
ที่สร้างวัตถุจากมันด้วย id
เป็นคีย์และรายการอาร์เรย์เป็นค่า
ตัวอย่างเช่น:
ให้ผู้ใช้ = [ {id: 'John', ชื่อ: "John Smith", อายุ: 20}, {id: 'Ann', ชื่อ: "Ann Smith", อายุ: 24}, {id: 'Pete', ชื่อ: "Pete Peterson", อายุ: 31}, - ให้ usersbyId = GroupById (ผู้ใช้); - // หลังจากการโทรเราควรมี: usersById = { John: {id: 'John', ชื่อ: "John Smith", อายุ: 20}, Ann: {id: 'Ann', ชื่อ: "Ann Smith", อายุ: 24}, Pete: {id: 'Pete', ชื่อ: "Pete Peterson", อายุ: 31}, - -
ฟังก์ชั่นดังกล่าวมีประโยชน์จริงๆเมื่อทำงานกับข้อมูลเซิร์ฟเวอร์
ในงานนี้เราคิดว่า id
นั้นไม่ซ้ำกัน อาจไม่มีรายการอาร์เรย์สองรายการที่มี id
เดียวกัน
โปรดใช้อาร์เรย์ .reduce
วิธีการแก้ไขในการแก้ปัญหา
เปิดแซนด์บ็อกซ์พร้อมการทดสอบ
ฟังก์ชั่น GroupById (อาร์เรย์) { return array.Reduce ((obj, value) => { obj [value.id] = ค่า; คืน OBJ; - -
เปิดโซลูชันพร้อมการทดสอบในแซนด์บ็อกซ์