เมื่อเร็วๆ นี้ ฉันเริ่มฝึกฝนทุกวันเกี่ยวกับ CodeWar และนี่คือบันทึกของคำถามแรกที่ได้รับการแก้ไขแล้ว: ไอโซแกรม
ในบันทึกนี้ ฉันจะไม่พูดถึงความซับซ้อนของพื้นที่หรือเวลา เนื่องจากฉันยังไม่คุ้นเคยกับ JS...
ไอโซแกรมเป็นประโยค (หรือ "สตริง") ที่ไม่มีคำซ้ำ
ในคำถามนี้ เรามีอินพุตเดียว (สตริง) และงานของเราคือการส่งคืนเอาต์พุต (จริงหรือเท็จ) เพื่อบอกว่าอินพุตนั้นเป็นไอโซแกรมหรือไม่
ทางออกแรกของฉัน
ในการแก้ปัญหา แนวคิดแรกของฉันคือการใช้ Set เพื่อจัดเก็บแต่ละคำในประโยค และหากคำนั้นถูกจัดเก็บไว้ (คำซ้ำ) ฟังก์ชัน isIsogram จะส่งกลับค่าเท็จ ถ้าคำทั้งหมดถูกข้ามไปและไม่มีการส่งกลับเท็จ ฟังก์ชันจะส่งกลับค่าจริง
function isIsogram(str){ const strL = str.toLowerCase().split('') // convert all words in the sentence to lowercase, and remove all blank. const strSet = {} for(let i = 0; i< strL.length; i++){ if(strSet[strL[i]]===0){ // if the word has been stored return false } else{ strSet[strL[i]] = 0 } } return true }
วิธีแก้ปัญหาของผู้อื่น
หลังจากส่งคำตอบแล้ว ฉันก็เริ่มค้นคว้าคำตอบของผู้อื่น:
อันแรกก็ใช้ชุดแก้โจทย์ด้วย
function isIsogram(str){ const strL = str.toLowerCase().split('') const setStrL = new Set(strL) return setStrL.size === strL.length }
อย่างไรก็ตาม ตรรกะคือการใช้คุณลักษณะของชุด —คีย์เฉพาะ
หากสตริงอินพุตมีคำที่ซ้ำกัน ขนาดของชุดที่แปลงจากสตริงอินพุตจะแตกต่างจากความยาวของสตริง
วิธีที่สอง ใช้ indexOf ใน JS เพื่อแก้คำถาม
function isIsogram(str){ const strL = str.toLowerCase().split('') return strL.every((current, index) => strL.indexOf(current) === index); }
ในโซลูชันนี้ เราจะสำรวจคำทั้งหมดในประโยค และหากดัชนีของคำปัจจุบันแตกต่างจากดัชนีที่ฟังก์ชัน "indexOf" ส่งคืน จะส่งคืนค่าเท็จ มิฉะนั้นจะคืนค่าจริง
ฟังก์ชัน "indexOf" จะส่งกลับดัชนีของคำที่พบ "แรก" ของประโยค ดังนั้นหากประโยคมีคำที่ซ้ำกัน ดัชนีก็จะแตกต่างออกไป มิฉะนั้น จะส่งกลับหมายเลขดัชนีเดียวกันเสมอ
แนวทางที่สามใช้นิพจน์ทั่วไป
function isIsogram(str){ return !/(\w).*\1/i.test(str) }
สำหรับวิธีแก้ปัญหานี้ ฉันศึกษาเป็นเวลา 2 ชั่วโมงเพื่อดูว่ามันทำงานอย่างไร
ประการแรก ฟังก์ชัน “ทดสอบ” ได้รับการออกแบบมาสำหรับนิพจน์ทั่วไปของ JS MDN กล่าวว่า:
วิธีการ RegExp
ที่ทดสอบการจับคู่ในสตริง มันจะคืนค่าจริงหรือเท็จ
ตอนนี้ ลองใช้ https://regex101.com/ เพื่อค้นหาคำอธิบายของนิพจน์ทั่วไป:
- “\w” จะจับคู่อักขระคำใดก็ได้ (เทียบเท่ากับ [a-zA-Z0–9_]) และ”()” จะทำให้การจับคู่ที่ตรงกันถูกจัดเก็บเป็นกลุ่ม
- “” ตรงกับอักขระใดๆ (ยกเว้นตัวยุติบรรทัด)
- “*” จับคู่โทเค็นก่อนหน้าระหว่างศูนย์และไม่จำกัดครั้ง มากที่สุดเท่าที่จะเป็นไปได้ โดยให้คืนตามต้องการ (โลภ)
- “\1” จับคู่ข้อความเดียวกับที่จับคู่ล่าสุดโดยกลุ่มการจับที่ 1 (ในกรณีนี้ มันจะจับคู่ข้อความเดียวกับที่จับคู่ล่าสุดด้วย \w)
- ตัวแก้ไข “i”: iไม่ละเอียดอ่อน การจับคู่ที่ไม่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ (ละเว้นตัวพิมพ์ของ [a-zA-Z])
ดังนั้น โดยทั่วไป “/(\w).*\1/i” จะจับคู่ประโยคในรูปแบบ “…(\w)…(\w)…”
“!/(\w).*\1/i.test(str)” จะทดสอบ “str” หาก “str” ตรงกับรูปแบบ “…(\w)…(\w)…” จากนั้นจึงส่งคืน เท็จมิฉะนั้นจะคืนค่าจริง