Swift Academy · บทเรียน

ข้อแลกเปลี่ยนระหว่าง lazy กับ eager

ทราบว่าเมื่อใดการประเมินแบบ lazy ช่วยหรือทำให้ช้าลง

บทเรียน 3 จาก 413 ขั้นตอน

ข้อแลกเปลี่ยนระหว่าง lazy กับ eager เป็นบทเรียน Swift Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Swift Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน

ไม่มีอาหารกลางวันฟรี

แบบขี้เกียจไม่ได้เร็วกว่าเสมอไป โดยแลกการจัดสรรหน่วยความจำล่วงหน้ากับค่าใช้จ่ายเมื่อเข้าถึงแต่ละครั้ง และเปลี่ยนเวลาที่ผลข้างเคียงทำงาน การเข้าใจข้อแลกเปลี่ยนเหล่านี้ช่วยให้คุณเลือกได้อย่างถูกต้อง

แบบขี้เกียจได้เปรียบ: ใช้ข้อมูลเพียงบางส่วน

ต้องการเพียงบางส่วนของการแปลงข้อมูลขนาดใหญ่มาก — แบบขี้เกียจจึงข้ามส่วนที่เหลือ:

let data = Array(1...1_000_000)
let top = data.lazy.map { $0 * 2 }.prefix(3)
print(Array(top))  // [2, 4, 6]  -- 999,997 transforms skipped

eager ได้เปรียบ: ใช้ซ้ำทั้งหมด

หากคุณวนซ้ำผลลัพธ์หลายครั้ง eager จะคำนวณเพียงครั้งเดียว ส่วนแบบขี้เกียจจะคำนวณใหม่ทุกครั้งที่วนซ้ำ:

let doubled = [1, 2, 3].map { $0 * 2 }  // computed once
print(doubled.reduce(0, +))  // 12
print(doubled.max()!)        // 6  -- no recompute

แบบขี้เกียจคำนวณใหม่

มุมมองแบบขี้เกียจเดียวกันจะทำงานซ้ำทุกครั้งที่วนซ้ำ:

var work = 0
let view = [1, 2, 3].lazy.map { (n: Int) -> Int in work += 1; return n }
_ = view.reduce(0, +)
_ = view.max()
print(work)  // 6  -- transformed twice

ค่าใช้จ่ายต่อสมาชิก

แต่ละขั้นตอนแบบขี้เกียจจะห่อ sequence ไว้ในอีก type หนึ่ง และเรียกผ่าน closures ทีละสมาชิก สำหรับอาร์เรย์ขนาดเล็กมาก ค่าใช้จ่ายนี้อาจมากกว่าหน่วยความจำที่ประหยัดได้

อาร์เรย์ขนาดเล็ก ใช้ eager ได้

สำหรับสมาชิกไม่กี่รายการที่ใช้ทั้งหมด ควรเลือก eager แบบธรรมดา — โค้ดเรียบง่ายกว่า และการจัดสรรหน่วยความจำก็มีค่าใช้จ่ายเล็กน้อย:

let nums = [3, 1, 2]
let sorted = nums.map { $0 + 1 }.sorted()
print(sorted)  // [2, 3, 4]

เวลาของผลข้างเคียงแตกต่างกัน

เมื่อใช้แบบขี้เกียจ เนื้อความของ closure จะทำงานช้ากว่าบรรทัดที่กำหนด closure นั้นไว้ หลีกเลี่ยงการพึ่งพาผลข้างเคียงภายในการแปลงแบบขี้เกียจ:

var log: [Int] = []
let v = [1, 2].lazy.map { (n: Int) -> Int in log.append(n); return n }
print(log)        // []  -- nothing ran yet
_ = Array(v)
print(log)        // [1, 2]

การดำเนินการที่บังคับให้ประเมินทันที

การดำเนินการบางอย่างจำเป็นต้องอ่าน sequence ทั้งหมดอยู่แล้ว ดังนั้นแบบขี้เกียจจึงไม่ให้ประโยชน์ในกรณีนี้:

let nums = Array(1...10)
print(nums.lazy.map { $0 * 2 }.sorted())  // sorted must see all -> [2,4,...,20]
print(nums.lazy.map { $0 }.count)         // count walks everything

แบบขี้เกียจร่วมกับการตรวจสอบสมาชิก

การดำเนินการแบบหยุดทันทีเมื่อได้คำตอบ เช่น contains(where:) จะได้ประโยชน์จากแบบขี้เกียจเมื่อข้อมูลขาเข้ามีขนาดใหญ่:

let big = Array(1...1_000_000)
let found = big.lazy.map { $0 * 2 }.contains { $0 == 8 }
print(found)  // true  -- stops at element 4

รายการตรวจสอบเพื่อการตัดสินใจ

ใช้แบบขี้เกียจเมื่อ: แหล่งข้อมูลมีขนาดใหญ่ AND คุณเก็บไว้เพียงบางส่วน (คำนำหน้า / รายการแรก / การตรวจสอบสมาชิก) AND คุณวนซ้ำเพียงครั้งเดียว ใช้ eager เมื่อ: อาร์เรย์มีขนาดเล็ก คุณนำผลลัพธ์กลับมาใช้ซ้ำ หรือความอ่านง่ายสำคัญกว่าการปรับประสิทธิภาพเพียงเล็กน้อย

let huge = Array(1...100_000)
let first = huge.lazy.filter { $0 % 9973 == 0 }.first
print(first!)  // 9973

วัดผล อย่าเดา

สัญชาตญาณด้านประสิทธิภาพมักไม่ถูกต้อง เมื่อเรื่องนี้สำคัญ ให้ทดสอบประสิทธิภาพทั้งสองรูปแบบด้วยข้อมูลที่ใกล้เคียงการใช้งานจริงก่อนตัดสินใจใช้แบบขี้เกียจ

let nums = Array(1...50)
let eager = nums.filter { $0 > 25 }.count
let lazyC = nums.lazy.filter { $0 > 25 }.count
print(eager == lazyC)  // true -- same answer, profile for speed

ตรวจสอบอย่างรวดเร็ว

เมื่อใดจึงควรเลือก eager แทนแบบขี้เกียจ

สรุป

คุณได้เรียนรู้ข้อแลกเปลี่ยนต่าง ๆ:

  • แบบขี้เกียจได้เปรียบเมื่อแหล่งข้อมูลมีขนาดใหญ่ และใช้ข้อมูลเพียงบางส่วนในการวนซ้ำครั้งเดียว
  • eager ได้เปรียบสำหรับอาร์เรย์ขนาดเล็กและผลลัพธ์ที่นำกลับมาใช้ซ้ำ (แบบขี้เกียจจะคำนวณใหม่)
  • ผลข้างเคียงในการแปลงแบบขี้เกียจจะทำงานภายหลัง — หลีกเลี่ยงการพึ่งพาผลข้างเคียงเหล่านั้น
  • วัดผลก่อนปรับประสิทธิภาพ

ถัดไป: การสร้าง sequence แบบขี้เกียจที่กำหนดเอง

เริ่มต้นได้ฟรี

เรียนรู้ Swift ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
122
บทเรียน
409

คำถามที่พบบ่อย

บทเรียน “ข้อแลกเปลี่ยนระหว่าง lazy กับ eager” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ข้อแลกเปลี่ยนระหว่าง lazy กับ eager” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Swift Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ข้อแลกเปลี่ยนระหว่าง lazy กับ eager”

ทราบว่าเมื่อใดการประเมินแบบ lazy ช่วยหรือทำให้ช้าลง คุณปฏิบัติ Swift Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Swift Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Swift Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “ข้อแลกเปลี่ยนระหว่าง lazy กับ eager” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Swift Academy นี้ได้ไหม

ได้ บทเรียน Swift Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. คุณสมบัติ lazy
  2. map และ filter แบบ lazy
  3. ข้อแลกเปลี่ยนระหว่าง lazy กับ eager
  4. การสร้างลำดับแบบ lazy ที่กำหนดเอง
← กลับไปที่ Swift Academy