在 Clojure 中更新深层嵌套结构
Updating deeply nested structures in clojure
我有这样的结构:
[["/1417612109-first-migration.clj" {:applied true :date-applied 1423233980}]
["/1417612450-second-migration.clj" {:applied false}]
["/1417615919-forth-migration.clj" {:applied false}]]
我最终需要操纵它并 return 它的新版本。为了找到我需要操作的值,我使用了 filter
和 first
,这给了我我想要的向量,例如:
["/1417612450-second-migration.clj" {:applied false}]
我的问题是;如何更新该特定项目的地图,而不必再次 map
整个地段?我可以以某种方式将以上内容用作参考吗?
您可以使用更新功能https://clojuredocs.org/clojure.core/update-in
(update-in my-vector [0 1 :applied] f)
其中 f 是一个接受旧值和 return 新值的函数。此示例将从您的第一个矢量更新地图中的应用值。它也适用于深层结构。有关更多信息,请参阅文档。
如果您不需要为其他目的返回匹配向量,即您只是为了更新它而找到它,那么使用映射而不是过滤器,首先,使用检查每个条目的函数查看是否需要更新和 returns changed/unchanged 条目是否合适。
(def test
[["/1417612109-first-migration.clj" {:applied true :date-applied 1423233980}]
["/1417612450-second-migration.clj" {:applied false}]
["/1417615919-forth-migration.clj" {:applied false}]])
(map #(if (:applied (second %))
% ; if applied is already true then use it unchanged
(assoc-in % [1 :applied] true)) ; if applied is false update it
test)
; (["/1417612109-first-migration.clj" {:applied true, :date-applied 1423233980}]
; ["/1417612450-second-migration.clj" {:applied true}]
; ["/1417615919-forth-migration.clj" {:applied true}])
如果您不需要将外部集合作为矢量,那么您可以将其设为地图,然后使用例如“/1417612450-second-migration.clj”作为关联或更新的键。
(def test-map
{"/1417612109-first-migration.clj" {:applied true :date-applied 1423233980}
"/1417612450-second-migration.clj" {:applied false}
"/1417615919-forth-migration.clj" {:applied false}})
(def result ["/1417612450-second-migration.clj" {:applied false}])
(assoc-in test-map [(first result) :applied] true)
;{"/1417612109-first-migration.clj" {:applied true, :date-applied 1423233980},
; "/1417612450-second-migration.clj" {:applied true},
;"/1417615919-forth-migration.clj" {:applied false}}
我有这样的结构:
[["/1417612109-first-migration.clj" {:applied true :date-applied 1423233980}]
["/1417612450-second-migration.clj" {:applied false}]
["/1417615919-forth-migration.clj" {:applied false}]]
我最终需要操纵它并 return 它的新版本。为了找到我需要操作的值,我使用了 filter
和 first
,这给了我我想要的向量,例如:
["/1417612450-second-migration.clj" {:applied false}]
我的问题是;如何更新该特定项目的地图,而不必再次 map
整个地段?我可以以某种方式将以上内容用作参考吗?
您可以使用更新功能https://clojuredocs.org/clojure.core/update-in
(update-in my-vector [0 1 :applied] f)
其中 f 是一个接受旧值和 return 新值的函数。此示例将从您的第一个矢量更新地图中的应用值。它也适用于深层结构。有关更多信息,请参阅文档。
如果您不需要为其他目的返回匹配向量,即您只是为了更新它而找到它,那么使用映射而不是过滤器,首先,使用检查每个条目的函数查看是否需要更新和 returns changed/unchanged 条目是否合适。
(def test
[["/1417612109-first-migration.clj" {:applied true :date-applied 1423233980}]
["/1417612450-second-migration.clj" {:applied false}]
["/1417615919-forth-migration.clj" {:applied false}]])
(map #(if (:applied (second %))
% ; if applied is already true then use it unchanged
(assoc-in % [1 :applied] true)) ; if applied is false update it
test)
; (["/1417612109-first-migration.clj" {:applied true, :date-applied 1423233980}]
; ["/1417612450-second-migration.clj" {:applied true}]
; ["/1417615919-forth-migration.clj" {:applied true}])
如果您不需要将外部集合作为矢量,那么您可以将其设为地图,然后使用例如“/1417612450-second-migration.clj”作为关联或更新的键。
(def test-map
{"/1417612109-first-migration.clj" {:applied true :date-applied 1423233980}
"/1417612450-second-migration.clj" {:applied false}
"/1417615919-forth-migration.clj" {:applied false}})
(def result ["/1417612450-second-migration.clj" {:applied false}])
(assoc-in test-map [(first result) :applied] true)
;{"/1417612109-first-migration.clj" {:applied true, :date-applied 1423233980},
; "/1417612450-second-migration.clj" {:applied true},
;"/1417615919-forth-migration.clj" {:applied false}}