EDIT #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
? Я предполагал, что при наличии дерева и пути применение пути к дереву приведет вас к исходному местоположению пути, а не частично туда.
ОБНОВЛЕНИЕ: я использовал следующее определение функции для компиляции пути узлов от начального до конечного местоположения:
(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, спасибо!