Как переместить элемент в структуре, возможно, с помощью молнии?

У меня есть эта структура:

 [{"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" []})}]

Заметки:

  1. Ходок продолжает идти, поэтому, если вы ищете однократную трансформацию, вы должны как-то это адаптировать. Я пытался добавить FIRST к вектору преобразования, но он все еще продолжает идти даже после нахождения одного из "b".
  2. Я пытался с помощью collect-one вместо get-in но мне не удалось.

Не стесняйтесь редактировать его, если найдете более удачное решение. Я все еще новичок в Призраке.

Другие вопросы по тегам