ฟังก์ชั่นเส้นทางของ Clojure zippers ไม่สมบูรณ์ใช่ไหม

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

คำถามเดิม:

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

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

ตัวอย่างเช่น:

(def test-zip (vector-zip [0 [1] [2 [3 [4] 5 [6 [7] [8]]]]]))
(-> test-zip 
    down right right down 
    right down right right
    node)

ให้ 5 แต่

(-> test-zip 
    down right right down 
    right down right right
    path)

ให้

[[0 [1] [2 [3 [4] 5 [6 [7] [8]]]]] [2 [3 [4] 5 [6 [7] [8]]]] [3 [4] 5 [6 [7] [8]]]]

ซึ่งไม่ใช่ตำแหน่งเดียวกัน (ไม่มีเอฟเฟกต์ของสามขั้นตอนสุดท้าย down right right)

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

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

อัปเดต: ฉันใช้คำจำกัดความฟังก์ชันต่อไปนี้เพื่อรวบรวมเส้นทางของโหนดจากตำแหน่งเริ่มต้นไปยังตำแหน่งสิ้นสุด:

(defn lca-path [start-loc end-loc]
  (let [sczip (z/root start-loc)
        start-path (z/path start-loc)
        start-node (z/node start-loc)
        end-path (z/path end-loc)
        end-node (z/node end-loc)
        lca-path (filter (set start-path) end-path)
        lca-node [(last lca-path)]
        lca-to-start (conj (vec (drop (count lca-path) start-path)) start-node)
        lca-to-end (conj (vec (drop (count lca-path) end-path)) end-node)
        ]

    (concat (reverse lca-to-start) lca-node lca-to-end))
  )

ได้รับอิทธิพลอย่างมากจากการแชทกับ @Mark Fisher ขอบคุณ!


person Oliver Mooney    schedule 08.05.2015    source แหล่งที่มา


คำตอบ (1)


ฉันคิดว่าคุณพูดถูก มันเป็นผู้ปกครองที่นำทางไป และนี่คือการยืนยัน ที่ไซต์นี้, path ส่งคืน "แผนผังย่อยทั้งหมดจากรากของแผนผังลงไปที่เหนือตำแหน่งปัจจุบัน"

สำหรับโครงสร้างของคุณ ต้นไม้คือ:

   A
 / | \
0  o  B
   | / \
   1 2  C __
       /|\  \
      3 o 5  o
        |   /|\
        4  6 o o
             | |
             7 8

ดังนั้น 3 โหนดที่ทำเครื่องหมาย A, B, C จึงเป็นโหนดพาเรนต์ที่นำไปสู่พาเรนต์ของ 5 ซึ่งก็คือ:

A: [0 [1] [2 [3 [4] 5 [6 [7] [8]]]]]
B: [2 [3 [4] 5 [6 [7] [8]]]]
C: [3 [4] 5 [6 [7] [8]]]

ซึ่งเป็นผลลัพธ์ที่คุณได้รับ

แก้ไข: ฉันสร้างฟังก์ชันนี้เพื่อค้นหาระหว่างสองค่าในเวกเตอร์และส่งกลับ path ระหว่างค่าเหล่านั้น สิ่งนี้ช่วยได้หรือไม่? ฉันไม่ใช่ผู้เชี่ยวชาญด้านซิป ดังนั้นนี่ก็เป็นการเรียนรู้สำหรับฉันเช่นกัน

(defn between [v s e]
  (let [zv (zip/vector-zip v)
        find-loc (fn [zv l]
                   (loop [loc zv]
                     (if (= l (zip/node loc))
                       loc 
                       (if (zip/end? loc)
                           nil
                           (recur (zip/next loc))))))
        sv (zip/vector-zip (-> (find-loc zv s) zip/up zip/node))
        e-in-sv (find-loc sv e)
        path-s-e (when (some? e-in-sv)
                   (zip/path e-in-sv))]
    path-s-e))

พบเส้นทางระหว่างพาเรนต์ของค่าเริ่มต้นและพาเรนต์ของค่าสิ้นสุด และคุณสามารถใช้ได้ดังนี้:

(def sov [0 [1] [2 [3 [4] 5 [6 [7] [8]]]]])
(between sov 2 6)
=> [[2 [3 [4] 5 [6 [7] [8]]]] [3 [4] 5 [6 [7] [8]]] [6 [7] [8]]]

ฉันกำลังเดินบนต้นไม้เพื่อค้นหาพาเรนต์ของค่าเริ่มต้น จากนั้นสร้างซิปใหม่จากพาเรนต์เพื่อให้เส้นทางถูกจำกัดจากจุดเริ่มต้น ฟังก์ชันตัวช่วย "find-loc" จะส่งคืนซิปสำหรับรายการที่คุณกำลังมองหา เช่น "5" ภายในเวกเตอร์ sv จึงเป็นเวกเตอร์พาเรนต์ที่มีค่าเริ่มต้น

หากไม่มีเส้นทางก็จะคืนค่าเป็นศูนย์เช่น ระหว่าง 1 ถึง 4 คุณจะต้องเคลื่อนที่ขึ้นไป 2 องค์ประกอบ

นี่เป็นการตอบสนองต่อความคิดเห็นของคุณที่ต้องหาค่าในโหนดสุดท้าย (เช่น 5 ใน [3 [4] 5 [6 [7] [8]]]) ซึ่งฉันไม่คิดว่าคุณต้องทำ แต่หากไม่มีตัวอย่างที่แท้จริงของสิ่งที่คุณกำลังทำอยู่นั้นยากที่จะแสดงความคิดเห็น บน.

อย่างไรก็ตาม อาจมีวิธีสำรวจ/ค้นหาค่าในเวกเตอร์ได้ดีกว่าฟังก์ชันแบบกำหนดเองมาก แต่อย่างที่ฉันบอกว่าซิปก็ค่อนข้างใหม่สำหรับฉันเช่นกัน

person Mark Fisher    schedule 08.05.2015
comment
ดังนั้นเมื่อคุณไปถึงแผนผังย่อยพาเรนต์ คุณต้องค้นหาโหนดที่ต้องการด้วยตนเองในลำดับต้นของแผนผังย่อยสุดท้ายหรือไม่ เนื่องจากโหนดจากมากไปน้อยในทันทีคือ 3 [4], 5 และ [6 [7] [8]] ซึ่งไม่ใช่การค้นหาที่กว้างเกินไปในกรณีนี้ แต่มันไม่แปลกหรอกหรือที่เส้นทางเดิมทั้งสี่จะกลับมาเหมือนเดิม? มีวิธีอื่นที่เป็นสำนวนในการจับภาพเส้นทางไปยังสถานที่ด้วยซิปที่ฉันขาดหายไปหรือไม่? - person Oliver Mooney; 08.05.2015
comment
ฉันกำลังแบ่งปันการเดินทางกับคุณในเรื่องนี้ ฉันได้อัปเดตคำตอบเพื่อรวมตัวค้นหาไว้เหนือเวกเตอร์ของคุณระหว่าง 2 จุด สิ่งนี้เหมาะสมกับสิ่งที่คุณพยายามทำให้สำเร็จหรือไม่? - person Mark Fisher; 08.05.2015
comment
นอกจากนี้ฉันคิดว่ามันเป็นเช่นนี้เพราะคุณใช้ vector-zip แบบง่าย ๆ แทนที่จะใช้ zip แบบกำหนดเองกับข้อมูลของคุณ - person Mark Fisher; 08.05.2015
comment
สิ่งนี้จะไม่ซ้ำกับฟังก์ชันการทำงานของฟังก์ชัน path ใช่หรือไม่ เมื่อคุณพบตำแหน่งเริ่มต้นและตำแหน่งสิ้นสุด และเส้นทางการโทรทั้งสองจุดแล้ว คุณสามารถทำ (filter (set start-path) end-path) เพื่อให้ได้บรรพบุรุษร่วมที่ต่ำที่สุดของทั้งสองจุด ฉันยังทำ lca-to-start-parent (drop (count lca-loc) start-path) เพื่อรับเส้นทางจากบรรพบุรุษร่วมที่ต่ำที่สุดไปยังจุดเริ่มต้น และ (drop (count lca-loc) end-path) สำหรับขาอีกข้างหนึ่งไปยังจุดสิ้นสุด ฉันชอบการนำไปใช้งานที่มีในตัวเองที่คุณมี และคุณจะใช้เหมือนกันได้อย่างไร เพื่อนำทางไปยังตำแหน่งแม่... - person Oliver Mooney; 08.05.2015
comment
เพิ่งเห็นความคิดเห็นถัดไปของคุณ - จริง ๆ แล้วฉันใช้เวกเตอร์เป็นตัวอย่างง่ายๆ เพื่อจับซิป ฉันใช้ซิปแบบกำหนดเองสำหรับข้อมูลจริงของฉัน แต่ต้องการแยกแยะว่าเป็นปัจจัยที่ซับซ้อน - person Oliver Mooney; 08.05.2015
comment
อาจจะใช่! ฉันพยายามทำความเข้าใจปัญหาของคุณให้ดีขึ้นและคิดว่าจะแบ่งปัน มีส่วนที่ดีในการเขียนโปรแกรม Clojure เกี่ยวกับการกำหนดเส้นทางระหว่าง 2 จุดในเขาวงกตโดยใช้ซิปที่กำหนดเองโดยใช้เส้นทาง (clojurebook.com) ฉันคิดว่าธรรมชาติของคำถามของคุณที่มีเส้นทางเดียวกันกับองค์ประกอบจำนวนเท่ากันนั้นเป็นคุณสมบัติของการใช้ vector-zipper มากกว่าที่จะเป็นปัญหาทั่วไปของ zippers .... และความคิดเห็นนี้ข้ามกับความคิดเห็นของคุณ :) - person Mark Fisher; 08.05.2015
comment
อาจเป็นที่น่าสังเกตเช่นกันว่าเราทั้งคู่ต่างถือว่าค่าที่ไม่ซ้ำกันสำหรับโหนด (จริงในกรณีของฉัน) - person Oliver Mooney; 08.05.2015