clojure - 通过键值交换地图查找中的嵌套特定项目,地图中的位置
问题描述
我们有一个带有此示例数据的光标或原子映射:
#<Cursor: [:customer] {:name Diego Peña,
:addresses [{:id 23, :province Madrid, :country 1, :descripcion aaeeeeeeee iii oooo4444, :locality Gali gali, :country_name SPAIN, :direccion Street Cierva, :id 3, :postalcode 30203, :principal true, :customer 17}
{:id 35, :province Madrid, :country nil, :descripcion yyy lalala3, :locality Lalala, :direccion calle Maria 3 , :postalcode 333, :principal false, :customer 17}
{:id 6, :province Madrid, :country 2, :descripcion otra direccioncita444, :locality Leleele, :country_name SPAIN, :direccion Direccion calle Ooo, :postalcode 1236, :main false, :customer 17}
{:id 27, :province Madrid, :country 1, :descripcion grandisima, :locality Alcantarilla, :country_name SPAIN, :direccion C/ 3 Mayo, :postalcode 3001, :main false, :customer 17}
]}>
我需要通过 id 更改搜索地址的值。我已经设法通过 id 的值找到地址:
(defn get-address [pk]
(->> @db/customer :addresses (filter #(= (int pk) (int (:id %)))) first)
)
我可以用这个更改所有地址::ok #(swap! db/customer assoc-in [:addresses] %)})
. 我需要从 API 响应中更改特定地址的数据。
我接近得到它,但使用这种方法我错过了项目的位置或索引:#(swap! db/client assoc-in [:addresses ¿position or index in map?] %)
我们有项目地址的 id。
也许这种方法是错误的,更好的方法?
解决方案
assoc、assoc-in、update和update-in函数也适用于向量。在 Clojure 中,向量是关联数据结构,其中键是数字索引 ( O..n
),值是 position 处的项目n
。
所以你可以这样做:
(assoc [:a :b :c] 1 :new-value)
;; ^ ^ ^
;; 0 1 2
;; => [:a :new-value :c]
根据您的示例,您将需要以下内容:
(defn address-index-by-id
"Take an `address` map and look it up by `:id` in the `addresses` list.
Return the numeric index where it was found, nil if not found."
[address addresses]
(->> (map-indexed vector addresses)
;; produce a seq `([0 val-at-index-0] … [n val-at-index-n])`
(filter (fn [[_index {:keys [id]}]] (= id (:id address)))) ;; filter by id
(ffirst) ;; get the index of the first match
))
(defn set-address
"Take a `customer` map and an `address` map. Will put the `address` in the
customer's addresses list. If an address with the same :id key is already
present in this list, it will be overwritten."
[customer address]
(if-let [existing-index (address-index-by-id address (:addresses customer))]
(assoc-in customer [:addresses existing-index] address)
(update customer :addresses conj address)))
用法:
(set-address {:name "Diego Peña"
:addresses []}
{:id 1
:province "Madrid"})
;; => {:name "Diego Peña", :addresses [{:id 1, :province "Madrid"}]}
(-> {:name "Diego Peña"
:addresses [{:id 1
:province "Madrid"
:main true}
{:id 2
:province "Barcelona"
:main false}]}
(set-address {:id 2
:province "Barcelona"
:main true})
(set-address {:id 1
:province "Madrid"
:main false}))
;; => {:name "Diego Peña", :addresses [{:id 1, :province "Madrid", :main false} {:id 2, :province "Barcelona", :main true}]}
;; And of course if your `customer` is stored in an Atom:
(swap! customer set-address {:id 1, :province "Madrid", :main true})
推荐阅读
- c# - 加载c#winforms后Tablelayoutpanel滚动到底部
- typescript - Firestore 安全规则:我应该如何测试特定操作(例如 get:) 是否完全禁用?
- python - 正则表达式匹配嵌套参数
- chart.js - 如何动态更新 Chartjs 图例标签颜色?
- java - 在 java 的 GUI 中,除了 .north、.south、.east、.west、.center 之外,我还能使用什么?
- reactjs - 使用不记名令牌响应 API 调用
- python - 如何将选择限制为 django ManyToManyField?
- c# - 将链方法结果委托给函数体
- libgit2sharp - LibGit2Sharp-SSH“无法启动 SSH 会话:无法交换加密密钥”
- c# - 如何根据特定值 MVC ASP.NET Core 查询数据库中的列