问题背景与股票交易有关。当进行销售时,我正在尝试更新特定股票的持有量。简化摘录
;; @holdings - an atom
{ "STOCK1" {:trades [Trade#{:id 100 :qty 50}, Trade#{ :id 140 :qty 50}]}
"STOCK2" ... }
Run Code Online (Sandbox Code Playgroud)
现在考虑到 的销售交易Trade{:id 200 :stock "STOCK1", :qty 75},我希望所持股份能够反映
{ "STOCK1" {:trades [Trade#{:id 100 :qty 0}, Trade#{ :id 140 :qty 25}]} }
;; or better drop the records with zero qty.
{ "STOCK1" {:trades [Trade#{ :id 140 :qty 25}]} }
Run Code Online (Sandbox Code Playgroud)
功能性的答案让我望而却步..我能看到的只是一个doseq带有原子的循环来保持状态(比如销售数量可能会被 1 次或 n 次交易所满足)——但感觉就像 Clojure 中的 C。
对此是否有更符合 clojure 的解决方案?地图看起来不太合适,因为每个记录处理都需要更新外部状态(待售数量 75 -> 25 -> 0)
免责声明:Clojure 新手,想学习。
(require '[com.rpl.specter :as s])
(let [stocks {"STOCK1" {:trades [{:trade/id 100 :trade/qty 50}, {:trade/id 140 :trade/qty 50}]}}
sale-trade {:trade/id 200 :trade/stock "STOCK1" :trade/qty 75}
trade-path [(s/keypath (:trade/stock sale-trade) :trades) s/ALL]
qty-path (conj trade-path :trade/qty)
[new-qty _] (reduce (fn [[new-amounts leftover] v]
(let [due-amount (min v leftover)]
[(conj new-amounts (- v due-amount)) (- leftover due-amount)]))
[[] (:trade/qty sale-trade)]
(s/select qty-path stocks))]
(->> stocks
(s/setval (s/subselect qty-path) new-qty)
(s/setval [trade-path #(zero? (:trade/qty %))] s/NONE)))
=> {"STOCK1" {:trades [#:trade{:id 140, :qty 25}]}}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
174 次 |
| 最近记录: |