ปูต้นฉบับเรียงกล่องสีเขียวบนทางลาดจากเตี้ยไปสูงและหยุดที่กล่องอำพันซึ่งวางผิดลำดับ

Rust Iterator::is_sorted_by_key: ตรวจลำดับโดยไม่สร้าง Vec สำรอง

พี่โชว์Engineering

บางระบบต้องปฏิเสธ event ที่ priority ถอยหลัง แต่ไม่จำเป็นต้อง sort หรือสร้าง collection ใหม่ Iterator::is_sorted_by_key เดินสมาชิกตามลำดับเดิมและหยุดเมื่อพบคู่ที่ผิดกติกา จึงเหมาะกับ validation ก่อนรับ batch ครับ

WHY: ตรวจตั๋วบนสายพาน ไม่ต้องยกลงมาเรียงใหม่

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

#[derive(Debug)]
struct Job { priority: u8, name: &'static str }

fn priorities_are_ordered(jobs: &[Job]) -> bool {
    jobs.iter().is_sorted_by_key(|job| job.priority)
}

#[test]
fn validates_original_order() {
    let ok = [
        Job { priority: 1, name: "thumbnail" },
        Job { priority: 1, name: "metadata" },
        Job { priority: 3, name: "publish" },
    ];
    assert!(priorities_are_ordered(&ok));
    assert_eq!(ok[0].name, "thumbnail");

    let reversed = [
        Job { priority: 2, name: "publish" },
        Job { priority: 1, name: "validate" },
    ];
    assert!(!priorities_are_ordered(&reversed));
    assert!(priorities_are_ordered(&[]));
}

HOW: key ต้องสะท้อนลำดับธุรกิจจริง

ฟังก์ชันถือค่าซ้ำว่าเรียงถูก เพราะตรวจแบบไม่ลดลง ถ้าธุรกิจต้องการเพิ่มขึ้นอย่างเคร่งครัด ให้ใช้ is_sorted_by พร้อม comparator ที่ปฏิเสธค่าซ้ำ หรือวนคู่ติดกันเองเพื่อคืนตำแหน่ง error ที่ละเอียดกว่า

Closure ถูกเรียกเพื่อสร้าง key ระหว่างเดิน iterator จึงควรราคาถูกและไม่มี side effect ถ้า key เป็น String ที่ต้อง allocate ทุกครั้ง อาจ normalize ก่อน หรือเทียบ reference ด้วย is_sorted_by แทน นอกจากนี้ iterator ถูก consume หลังตรวจ ถ้าต้องใช้ข้อมูลต่อให้ยืมผ่าน .iter() เหมือนตัวอย่าง หรือออกแบบ pipeline ให้ validation เป็นขั้นเดียวกับการประมวลผล

Recap

  • ใช้ is_sorted_by_key เพื่อตรวจลำดับเดิม ไม่ใช่จัดเรียงข้อมูล
  • ตกลงก่อนว่าค่าซ้ำยอมรับได้หรือไม่
  • ให้ key extraction ราคาถูกและ deterministic
  • จำไว้ว่า iterator ถูก consume
  • ถ้าต้องบอก index ที่ผิด ให้เขียน validation ที่เก็บตำแหน่งเพิ่ม