อิกัวนาต้นฉบับกำลังชี้หมุดต่ำสุดและสูงสุดบนรางข้อมูลเส้นเดียวในห้องทำงานสว่าง

Zig std.mem.findMinMax: หา index ค่าน้อยสุดและมากสุดในรอบเดียว

พี่โชว์Engineering

ถ้าต้องรู้ทั้งตำแหน่งต่ำสุดและสูงสุดของ slice เราไม่จำเป็นต้องเดินข้อมูลสองเที่ยวครับ std.mem.findMinMax คืน index ทั้งคู่จาก pass เดียว เหมือนพนักงานเช็กชั้นวางที่จดของเบาสุดกับหนักสุดระหว่างเดินรอบเดียว

HOW: ปิดเงื่อนไข slice ว่างก่อนเรียก

ฟังก์ชันนี้ต้องรับ slice ที่มีอย่างน้อยหนึ่ง element เราจึงทำ wrapper คืน null เมื่อ input ว่าง แล้วค่อยแปลง index เป็น value ตามงานของเรา

const std = @import("std");

fn minMax(values: []const i32) ?struct { min: i32, max: i32 } {
    if (values.len == 0) return null;
    const indexes = std.mem.findMinMax(i32, values);
    return .{ .min = values[indexes[0]], .max = values[indexes[1]] };
}

test "find min and max in one pass" {
    const values = [_]i32{ 8, -3, 8, 4, 21, -3 };
    const result = minMax(&values).?;
    try std.testing.expectEqual(@as(i32, -3), result.min);
    try std.testing.expectEqual(@as(i32, 21), result.max);
    try std.testing.expect(minMax(&[_]i32{}) == null);
}

Index สำคัญกว่าค่าในบางงาน

API คืน index เพราะผู้เรียกอาจต้องรู้ตำแหน่งของ anomaly, timestamp หรือ record เต็ม ไม่ใช่เพียงตัวเลข หากค่าซ้ำ ต้องตรวจ behavior จาก version ที่ pin และอย่าออกแบบ logic ที่พึ่งว่าจะได้ duplicate ตัวแรกหรือตัวท้ายโดยไม่เขียน test

สำหรับ stream ที่เก็บ slice ไม่ได้ ให้รักษา min/max ระหว่างอ่านเอง ส่วน slice ที่อยู่ใน memory แล้ว findMinMax ทำ intent ชัดและลดโอกาสที่ลูปสองชุดใช้ comparator ไม่ตรงกัน

Recap

  • เช็ก input ว่างก่อนเรียก
  • ใช้ index เพื่ออ้าง record ต้นฉบับเมื่อจำเป็น
  • เขียน test ค่าติดลบและค่าซ้ำ
  • ใช้ accumulator เองหากข้อมูลมาแบบ streaming