如何在结构中移动元素,可能使用拉链?
How to move an element within a structure, possibly with zippers?
我有这样的结构:
[{"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)
作为使用 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" []})}]
备注:
- 助行器一直在行走,所以如果您正在寻找一次性转换,您应该以某种方式对其进行调整。我尝试将
FIRST
添加到变换向量,但即使在找到 "b" 之一后它仍然继续行走。
- 我尝试使用
collect-one
而不是 get-in
但我没有成功。
如果您找到更好的解决方案,请随时对其进行编辑。我对幽灵还是个新手。
这会做我想做的事:
(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))))))
但它只适用于这个确切的结构。嵌套更多元素会破坏算法。
我有这样的结构:
[{"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)
作为使用 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" []})}]
备注:
- 助行器一直在行走,所以如果您正在寻找一次性转换,您应该以某种方式对其进行调整。我尝试将
FIRST
添加到变换向量,但即使在找到 "b" 之一后它仍然继续行走。 - 我尝试使用
collect-one
而不是get-in
但我没有成功。
如果您找到更好的解决方案,请随时对其进行编辑。我对幽灵还是个新手。
这会做我想做的事:
(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))))))
但它只适用于这个确切的结构。嵌套更多元素会破坏算法。