РЕДАКТИРОВАТЬ # 2: Весь этот вопрос и исследование были основаны на моем отсутствующем фундаментальном понятии молнии; что они представляют собой перспективу в структуре данных с точки зрения конкретного узла. Таким образом, застежка-молния всегда - пара текущего узла, а остальная часть дерева выглядит с точки зрения этого узла. Сначала я пытался создать целую новую структуру с застежкой-молнией, а сама молния была всем, что мне нужно, все время. Я оставлю все это для потомков, в надежде, что кому-то это поможет (или это служит предупреждением для любых преемников!).Clojure zipper функция пути не завершена?
Оригинальный вопрос:
Я пытаюсь получить мою голову вокруг с помощью застежки-молнии, чтобы манипулировать деревьев. Конкретная проблема заключается в том, что мне нужно генерировать на маршрутах времени выполнения между двумя узлами, которые соответствуют произвольным критериям в произвольном дереве.
Я думал, что могу использовать функцию 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
функции? Я предположил, что, учитывая дерево и путь, применение пути к дереву приведет вас к исходному расположению пути, а не отчасти там.
UPDATE: Я использовал следующее определение функции для компиляции пути узлов от начального местоположения до конечного местоположения:
(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 Фишер, спасибо !
Итак, как только вы попадаете в родительское поддерево, вам нужно искать требуемый узел вручную в непосредственных потомках последнего поддерева? Учитывая, что сразу же нисходящие узлы «3». '[4]', '5' и' [6 [7] [8]] 'это не слишком широкий поиск в этом случае. Но разве не странно, что тот же путь возвращается для всех четырех мест? Есть ли какой-нибудь другой идиоматический способ захвата маршрута к месту на молнии, который я пропускаю? –
Я как бы разделяю путешествие с вами на этом. Я обновил свой ответ, чтобы включить искатель над вашим вектором между двумя точками. Соответствует ли это тому, что вы пытаетесь достичь? –
Также я думаю, что это так, потому что вы используете простые векторные почтовые индексы, а не какую-то обычную молнию поверх своих данных. –