问题
I have this structure:
[{"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" []}]}]
I'm trying to write an algorithm to move and element within a vector. For example in the last element, it has children
vector with:
"children" [{"a" {"b" 9 "c" 10} "children" []} {"a" {"b" 10 "c" 10} "children" []}]
My function is supposed to search for a specific nested map - let's say, find the map where it is the value 10
for its b
property. I will locate {"a" {"b" 10 "c" 10} "children" []}
. Once I found it, I need to change its location with the vector. Let's assume, that children
will become:
"children" [{"a" {"b" 10 "c" 10} "children" []} {"a" {"b" 9 "c" 10} "children" []}]
With Zipper, I was able to traverse and locate the nested map but not sure how to move it within the vector.
Here is how my zipper is created:
(z/zipper #(contains? % "children") #(get % "children") (fn [_ c] c) data-structure)
回答1:
As an alternative solution using specter:
(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)
Returns:
[{"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" []})}]
Notes:
- The walker keeps walking, so if you're looking for a once-only transformation you should adapt this somehow. I tried adding
FIRST
to the transform vector but it still keeps walking even after finding one of the "b"s. - I tried using
collect-one
instead of theget-in
but I did not succeed.
Feel free to edit it if you find a nicer solution. I'm still new to specter.
回答2:
This will do what I want:
(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))))))
But it is only working for this exact structure. Nesting more elements is breaking the algorithm.
来源:https://stackoverflow.com/questions/32142532/how-to-move-an-element-within-a-structure-possibly-with-zippers