簡體   English   中英

使用assoc-in永久更改地圖Clojure中的值

[英]Using assoc-in to permanently change a value in a map Clojure

對於大量問題深表歉意。

我有一張紙牌圖:

    (def cards
  {
    :card1 {:name "Wisp"              :type "Monster"     :damage 1   :health 1   :cost 0   :ability 0 :active true}
    :card2 {:name "Spider Tank"       :type "Monster"     :damage 3   :health 4   :cost 3   :ability 0 :active true}
    :card3 {:name "Boulder Fist Ogre" :type "Monster"     :damage 6   :health 7   :cost 6   :ability 0 :active true}
    :card4 {:name "Bloodfen Raptor"   :type "Monster"     :damage 3   :health 2   :cost 2   :ability 0 :active true}
    :card5 {:name "Chillwind Yeti"    :type "Monster"     :damage 4   :health 5   :cost 4   :ability 0 :active true}
    :card6 {:name "Magma Rager"       :type "Monster"     :damage 5   :health 1   :cost 3   :ability 0 :active true}
    :card7 {:name "War Golem"         :type "Monster"     :damage 7   :health 7   :cost 7   :ability 0 :active true}
    :card8 {:name "Oasis Snapjaw"     :type "Monster"     :damage 2   :health 7   :cost 4   :ability 0 :active true}
    :card9 {:name "River Crocolisk"   :type "Monster"     :damage 2   :health 3   :cost 2   :ability 0 :active true}
    :card10 {:name "Murloc Raider"    :type "Monster"     :damage 2   :health 1   :cost 1   :ability 0 :active true}
    :card11 {:name "Northshire Cleric":type "Monster"     :damage 1   :health 3   :cost 1   :ability 2 :active true}
    :card12 {:name "Nat Peagle"       :type "Monster"     :damage 0   :health 4   :cost 2   :ability 4 :active true}
    :card13 {:name "Molten Giant"     :type "Monster"     :damage 8   :health 8   :cost 20  :ability 0 :active true}
    }
 )

這些卡在組成我的董事會的列表中:

(def board1 (list (:card3 cards) (:card4 cards) (:card11 cards) nil nil nil nil))

我要做的是將卡上的活動標志從true更改為false。

我知道我可以直接通過以下方式對我的卡片收集執行此操作:

user=> (assoc-in (:card11 cards) [:active] false)
{:ability 2, :name "Northshire Cleric", :type "Monster", :damage 1, :active false, :health 3, :cost 1}

我正在嘗試構建一個功能,當給定一個集合(板)和一個數字(第n個)卡時。 使此板上的此卡永久錯誤。

我一直在嘗試原子,但到目前為止還沒有喜悅。

(test-function board1 1)

(defn test-function [coll number]
  (let [test (atom coll)]
    (swap! test assoc-in (get (nth @test number)) [:active] false)
    (println test)))

我想知道我在做什么錯,以及是否有一種更清潔的方法而不使用原子。

您需要在let塊之外聲明原子。 您擁有它的方式,每次都會重新綁定它。 atom是有狀態事物的不錯選擇,因此應這樣聲明您的原子:

(def cards (atom
  {:card1 {:name "Wisp" :active true}
   :card2 {:name "Spider Tank" :active true}}))

然后,您可以編寫函數以將false交換為false如下所示:

(defn myfunc [coll number]
  (swap! coll assoc-in [(str :card number) :active] false ))

您不需要兩種不同的功能,盡管其中一種用於設置為true ,另一種用於設置為false 您應該下一步,讓它讀取當前的布爾值,然后將相反的值assoc-in (還請注意,我將樣本數據樣本保持為很小)。 ;)

JT93

根據您的評論,您希望消除atom ,並采用干凈的更新方法。

如果您可以在問題中提供更多信息來永久性地闡明您的意思。 例如:您是否要在整個執行周期內保持卡的板狀態? 如果是這樣,盡管Clojure另外還有一些其他方法,您可能需要使用atom

首先,考慮將board1的定義board1為向量而不是列表。 然后,您可以消除神秘的邏輯,而只需很少吹牛就可以使用assoc-in

(def board1 [(:card3 cards) (:card4 cards) (:card11 cards) nil nil nil nil])

(defn test-function [coll number]
    (assoc-in coll [number :active] false))

(clojure.pprint/pprint (test-function board1 0))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM