เวกเตอร์

ใน Scheme เวกเตอร์เป็นอีกหนึ่งโครงสร้างข้อมูลพื้นฐานที่ใช้ในการจัดกลุ่มค่า ต่างจากรายการตรงที่เวกเตอร์จะมีขนาดคงที่ คอลเลกชันขององค์ประกอบที่จัดทำดัชนีแล้ว ช่วยให้เข้าถึงและอัปเดตแบบสุ่มได้รวดเร็วยิ่งขึ้น แต่ละองค์ประกอบในเวกเตอร์สามารถเป็นประเภทใดก็ได้ รวมถึงเวกเตอร์อื่นด้วย เวกเตอร์แสดงโดยใช้ # ตามด้วยวงเล็บ #(1 2 3)

แม้ว่าเวกเตอร์และรายการอาจดูคล้ายกัน แต่ก็มีจุดประสงค์ที่แตกต่างกันในการเขียนโปรแกรม Scheme:

  • รายการมักใช้สำหรับการดำเนินการแบบเรียกซ้ำและโครงสร้างไดนามิก เนื่องจากการใช้งานโหนดที่เชื่อมโยงช่วยให้การจัดการจุดเริ่มต้นและการสำรวจเส้นทางมีประสิทธิภาพผ่านการสลายตัวแบบเรียกซ้ำ

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

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

เวกเตอร์อย่างง่าย

(vector 1 2 3)
  • สร้างเวกเตอร์ของสามองค์ประกอบ: 1, 2 และ 3

ผลลัพธ์: #(1 2 3)

การเข้าถึงองค์ประกอบเวกเตอร์

เข้าถึงองค์ประกอบในเวกเตอร์ได้โดยใช้ขั้นตอน vector-ref โดยจะดึงข้อมูลองค์ประกอบจากดัชนีที่ระบุ (เริ่มจาก 0)

(define my-vector (vector 1 2 3))
(vector-ref my-vector 0)  ; Retrieves the element at index 0
(vector-ref my-vector 1)  ; Retrieves the element at index 1

การวนซ้ำ: การประมวลผลแต่ละองค์ประกอบในเวกเตอร์

คุณสามารถวนซ้ำผ่านเวกเตอร์โดยใช้การวนซ้ำหรือการเรียกซ้ำ Scheme จัดเตรียม vector-length เพื่อกำหนดขนาดของเวกเตอร์ ต่อไปนี้เป็นวิธีง่ายๆ ในการพิมพ์ทุกองค์ประกอบในเวกเตอร์:

(define (print-elements vec)
  (let loop ((i 0))
    (if (< i (vector-length vec))
      (begin
        (lumi-message (number->string (vector-ref vec i))) ; Print the element
        (loop (+ i 1)))                                    ; Process the next index
      (lumi-message "done"))))                             ; End loop
  • กรณีฐาน: หากดัชนี i ถึงความยาวของเวกเตอร์ ให้หยุดการวนซ้ำ
  • กรณีแบบเรียกซ้ำ: พิมพ์องค์ประกอบที่ดัชนี i จากนั้นเพิ่มค่า i

ตัวอย่างการใช้งาน

(print-elements (vector 1 2 3))

ผลลัพธ์:

  • "1"
  • "2"
  • "3"

ผลลัพธ์: “เสร็จสิ้น”

เวกเตอร์ผสม

เวกเตอร์สามารถรวมองค์ประกอบประเภทต่างๆ ได้ รวมถึงสตริง บูลีน ตัวเลข เวกเตอร์อื่นๆ หรือแม้แต่ผลลัพธ์ของนิพจน์:

(vector 42 "hello" #t (vector 1 2) (+ 3 4))

สิ่งนี้จะสร้างเวกเตอร์ด้วย:

  • ตัวเลข (42)
  • สตริง ("hello")
  • บูลีน (#t)
  • เวกเตอร์อีกอัน (#(1 2))
  • ผลลัพธ์ของนิพจน์ ((+ 3 4) ซึ่งประเมินเป็น 7)

ผลลัพธ์: #(42 "hello" #t #(1 2) 7)

การสร้างเวกเตอร์

เวกเตอร์ถูกสร้างขึ้นโดยใช้ vector หรือโดยใช้ make-vector เพื่อสร้างเวกเตอร์ที่มีขนาดคงที่พร้อมค่าเริ่มต้น

(make-vector 5 0)

สร้างเวกเตอร์ขนาด 5 โดยมีองค์ประกอบทั้งหมดเริ่มต้นเป็น 0

ผลลัพธ์: #(0 0 0 0 0)

การอัปเดตเวกเตอร์

ขั้นตอน vector-set! จะอัปเดตองค์ประกอบในเวกเตอร์ที่ดัชนีที่ระบุ

(define my-vector (vector 1 2 3))
(vector-set! my-vector 1 42)  ; Sets the second element to 42
my-vector

ผลลัพธ์: #(1 42 3)

กำลังตรวจสอบเวกเตอร์

กระบวนการ vector? จะตรวจสอบว่าค่าที่กำหนดเป็นเวกเตอร์หรือไม่

(vector? (vector 1 2 3))  ; Checks if #(1 2 3) is a vector
(vector? 42)              ; Checks if 42 is a vector

ผลลัพธ์:

  • (vector? (vector 1 2 3)) ส่งกลับ #t (จริง)
  • (vector? 42) ส่งคืน #f (เท็จ)

เวกเตอร์และพฤติกรรมการอ้างอิงใน Scheme เวกเตอร์ไม่แน่นอนและส่งผ่านโดยการอ้างอิง ซึ่งหมายความว่าเมื่อคุณส่งเวกเตอร์ไปยังฟังก์ชัน ฟังก์ชันจะสามารถแก้ไขเวกเตอร์ดั้งเดิมได้โดยตรง การเปลี่ยนแปลงใดๆ ที่ทำกับเวกเตอร์ภายในฟังก์ชันจะมีผลภายนอกฟังก์ชันด้วย ลักษณะการทำงานนี้มีประโยชน์สำหรับการแบ่งปันและอัปเดตข้อมูลข้ามฟังก์ชันต่างๆ ได้อย่างมีประสิทธิภาพ แต่ยังต้องใช้ความระมัดระวังเพื่อหลีกเลี่ยงผลข้างเคียงที่ไม่ได้ตั้งใจ

ตัวอย่าง: การแก้ไขเวกเตอร์ในฟังก์ชัน

นี่คือตัวอย่างที่แสดงให้เห็นว่าเวกเตอร์ถูกส่งผ่านโดยการอ้างอิงและแก้ไขอย่างไร:

(define (modify-vector vec index new-value)
  (vector-set! vec index new-value))  ; Updates the vector at the specified index

(define my-vector (vector 10 20 30))
(modify-vector my-vector 1 99)         ; Modifies the second element to 99
my-vector                              ; The original vector is now updated

ผลลัพธ์: #(10 99 30)

คำอธิบายทีละขั้นตอน

  1. สร้างเวกเตอร์: my-vector เริ่มต้นได้ด้วยค่า 10, 20 และ 30
  2. ส่งผ่านไปยังฟังก์ชัน: my-vector ถูกส่งผ่านไปยัง modify-vector พร้อมด้วยดัชนีและค่าใหม่ที่จะอัปเดต
  3. แก้ไขในฟังก์ชัน: ขั้นตอน vector-set! จะอัปเดตค่าที่ดัชนีที่ระบุโดยตรงในเวกเตอร์ดั้งเดิม
  4. สะท้อนการเปลี่ยนแปลง: เนื่องจากเวกเตอร์ถูกส่งผ่านโดยการอ้างอิง การเปลี่ยนแปลงที่ทำภายในฟังก์ชันจึงสะท้อนให้เห็นในเวกเตอร์ดั้งเดิม

ผลกระทบของการอ้างอิงแบบผ่าน

  • ประสิทธิภาพ: การส่งผ่านเวกเตอร์โดยการอ้างอิงมีประสิทธิภาพเนื่องจากจะหลีกเลี่ยงการคัดลอกโครงสร้างขนาดใหญ่
  • ผลข้างเคียง: โปรดใช้ความระมัดระวังเมื่อแชร์เวกเตอร์ข้ามฟังก์ชันต่างๆ เพื่อหลีกเลี่ยงการแก้ไขข้อมูลที่แชร์โดยไม่ได้ตั้งใจ

การดำเนินการกับเวกเตอร์

Scheme มีขั้นตอนในตัวหลายอย่างสำหรับการทำงานกับเวกเตอร์ รวมไปถึง:

  • vector-length: ส่งกลับจำนวนองค์ประกอบในเวกเตอร์
  • vector->list: แปลงเวกเตอร์ให้เป็นรายการ
  • list->vector: แปลงรายการให้เป็นเวกเตอร์
(vector-length (vector 1 2 3))         ; Returns 3
(vector->list (vector 1 2 3))          ; Converts vector to list: (1 2 3)
(list->vector (list 1 2 3))            ; Converts list to vector: #(1 2 3)

ผลลัพธ์:

  • (vector-length (vector 1 2 3)) กลับมา 3
  • (vector->list (vector 1 2 3)) กลับมา (1 2 3)
  • (list->vector (list 1 2 3)) กลับมา #(1 2 3)

เวกเตอร์ที่ซ้อนกัน

เวกเตอร์ใน Scheme สามารถมีเวกเตอร์อื่นเป็นองค์ประกอบ ทำให้เกิดโครงสร้างที่ซ้อนกัน

(define nested-vector (vector (vector 1 2) (vector 3 4) (vector 5)))

สร้างเวกเตอร์ที่มีองค์ประกอบ 3 ส่วน ซึ่งแต่ละองค์ประกอบก็เป็นเวกเตอร์ในตัวมันเอง

ผลลัพธ์: #(#(1 2) #(3 4) #(5))

การเข้าถึงข้อมูลที่ซ้อนกัน

หากต้องการเข้าถึงองค์ประกอบภายในเวกเตอร์ที่ซ้อนกัน ให้ใช้ vector-ref หลายครั้งเพื่อเลื่อนดูโครงสร้าง

ตัวอย่าง: การเข้าถึงองค์ประกอบ

(vector-ref nested-vector 0)              ; Retrieves the first element: #(1 2)
(vector-ref (vector-ref nested-vector 0) 1) ; Retrieves the second element of the first vector: 2

สรุป

  • เวกเตอร์ ใน Scheme มีขนาดคงที่ โครงสร้างข้อมูลที่จัดทำดัชนีไว้
  • ใช้ vector เพื่อสร้างเวกเตอร์ vector-ref เพื่อเข้าถึงองค์ประกอบ และ vector-set! เพื่ออัปเดตองค์ประกอบ
  • ขั้นตอนในตัว เช่น vector-length, vector->list และ list->vector ช่วยให้การดำเนินงานมีความยืดหยุ่น
  • เวกเตอร์ที่ซ้อนกันทำให้เกิดโครงสร้างข้อมูลที่ซับซ้อนและเป็นลำดับชั้น