เมื่อเร็วๆ นี้ ฉันเริ่มฝึกฝนทุกวันเกี่ยวกับ 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/ เพื่อค้นหาคำอธิบายของนิพจน์ทั่วไป:

  1. “\w” จะจับคู่อักขระคำใดก็ได้ (เทียบเท่ากับ [a-zA-Z0–9_]) และ”()” จะทำให้การจับคู่ที่ตรงกันถูกจัดเก็บเป็นกลุ่ม
  2. “” ตรงกับอักขระใดๆ (ยกเว้นตัวยุติบรรทัด)
  3. “*” จับคู่โทเค็นก่อนหน้าระหว่างศูนย์และไม่จำกัดครั้ง มากที่สุดเท่าที่จะเป็นไปได้ โดยให้คืนตามต้องการ (โลภ)
  4. “\1” จับคู่ข้อความเดียวกับที่จับคู่ล่าสุดโดยกลุ่มการจับที่ 1 (ในกรณีนี้ มันจะจับคู่ข้อความเดียวกับที่จับคู่ล่าสุดด้วย \w)
  5. ตัวแก้ไข “i”: iไม่ละเอียดอ่อน การจับคู่ที่ไม่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ (ละเว้นตัวพิมพ์ของ [a-zA-Z])

ดังนั้น โดยทั่วไป “/(\w).*\1/i” จะจับคู่ประโยคในรูปแบบ “…(\w)…(\w)…”

“!/(\w).*\1/i.test(str)” จะทดสอบ “str” หาก “str” ตรงกับรูปแบบ “…(\w)…(\w)…” จากนั้นจึงส่งคืน เท็จมิฉะนั้นจะคืนค่าจริง