Как переместить элемент в структуре, возможно, с помощью молнии?
У меня есть эта структура:
[{"a" {"b" 1 "c" 2}
"children" [{"a" {"b" 3 "c" 4} "children" []}]}
{"a" {"b" 5 "c" 6} "children" []}
{"a" {"b" 7 "c" 8}
"children" [{"a" {"b" 9 "c" 10} "children" []} {"a" {"b" 10 "c" 10} "children" []}]}]
Я пытаюсь написать алгоритм для перемещения и элемента в векторе. Например, в последнем элементе, он имеет children
вектор с:
"children" [{"a" {"b" 9 "c" 10} "children" []} {"a" {"b" 10 "c" 10} "children" []}]
Моя функция должна искать конкретную вложенную карту - скажем, найти карту, где это значение 10
для его b
имущество. Я найду {"a" {"b" 10 "c" 10} "children" []}
, Как только я нашел это, мне нужно изменить его местоположение с вектором. Давайте предположим, что children
станет:
"children" [{"a" {"b" 10 "c" 10} "children" []} {"a" {"b" 9 "c" 10} "children" []}]
С помощью Zipper я смог пройти и найти вложенную карту, но не знал, как ее перемещать в векторе.
Вот как создается моя молния:
(z/zipper #(contains? % "children") #(get % "children") (fn [_ c] c) data-structure)
2 ответа
Это будет делать то, что я хочу:
(defn update-tree [editable? edit loc]
(loop [loc loc]
(if (z/end? loc)
(z/root loc)
(if (editable? (z/node loc))
(recur (-> loc z/up (z/edit edit) z/up z/next))
(recur (z/next loc))))))
Но это работает только для этой точной структуры. Вложение большего количества элементов нарушает алгоритм.
В качестве альтернативного решения используется призрак:
(def z [
{"a" {"b" 1 "c" 2}
"children" [{"a" {"b" 3 "c" 4}
"children" []}]}
{"a" {"b" 5 "c" 6}
"children" []}
{"a" {"b" 7 "c" 8}
"children" [{"a" {"b" 9 "c" 10}
"children" []}
{"a" {"b" 10 "c" 10}
"children" []}]}])
(transform
(walker (fn [x]
(and
(vector? x)
(some
#(= 10
(get-in % ["a" "b"]))
x))))
reverse
z)
Возвращает:
[{"a" {"b" 1, "c" 2}, "children" [{"a" {"b" 3, "c" 4}, "children" []}]}
{"a" {"b" 5, "c" 6}, "children" []}
{"a" {"b" 7, "c" 8},
"children"
({"a" {"b" 10, "c" 10}, "children" []}
{"a" {"b" 9, "c" 10}, "children" []})}]
Заметки:
- Ходок продолжает идти, поэтому, если вы ищете однократную трансформацию, вы должны как-то это адаптировать. Я пытался добавить
FIRST
к вектору преобразования, но он все еще продолжает идти даже после нахождения одного из "b". - Я пытался с помощью
collect-one
вместоget-in
но мне не удалось.
Не стесняйтесь редактировать его, если найдете более удачное решение. Я все еще новичок в Призраке.