2013-04-13 12 views
6

मैं क्लोजर में राज्य के चारों ओर अपना सिर लपेट रहा हूं। मैं उन भाषाओं से आती हूं जहां राज्य को उत्परिवर्तित किया जा सकता है। उदाहरण के लिए, पायथन में, मैं एक शब्दकोश बना सकता हूं, कुछ स्ट्रिंग => पूर्णांक जोड़े को अंदर रखता हूं, और फिर शब्दकोश पर चलता हूं और मानों को बढ़ाता हूं।मानचित्र में मूल्य वृद्धि कैसे करें

मैं मूर्खतापूर्ण क्लोजर में यह कैसे करूं?

उत्तर

1

बस produce एक नया नक्शा और इसका इस्तेमाल करते हैं:

(def m {:a 3 :b 4}) 

(apply merge 
    (map (fn [[k v]] {k (inc v) }) m)) 

; {:b 5, :a 4} 
+0

एक मूल्य के बारे में कैसे? तो अगर मैं चाहता हूं कि {ए: 7: बी 4}। क्या होगा यदि मेरे पास पूर्णांक के मानचित्रों का नक्शा है और कहें key1 => subkey1 => integer ++ के मान में वृद्धि करना चाहते हैं? –

+1

@ डेविडविल्लियम्स (अपडेट-इन-मैप [: बी] inc) ;; => {: 1,: बी 3} –

+0

समझ गया, यह एक नया नक्शा बनाता है, सही? मैं सोच रहा हूं कि यह राज्य को कठिन बना देता है। उदाहरण के लिए, बेयस क्लासिफायरफायर बनाने के लिए, मुझे लगातार बहुस्तरीय संरचना में अद्यतन चीजों की लम्बाई रखने की आवश्यकता है। key1 => subkey1 => पूर्णांक। क्या मुझे सोम dosync और स्वैप जादू करने की ज़रूरत होगी? –

7
(def my-map {:a 1 :b 2}) 
(zipmap (keys my-map) (map inc (vals my-map))) 
;;=> {:b 3, :a 2} 

कुंजी के द्वारा केवल एक मान अद्यतन करने के लिए:

(update-in my-map [:b] inc) ;;=> {:a 1, :b 3} 

Clojure 1.7 के बाद से यह भी संभव है update उपयोग करने के लिए:

(update my-map :b inc) 
2

एकाधिक मानों को अपडेट करने के लिए, आप पहले से भरे हुए संचयक को कम करने और निम्न संग्रह के उस सदस्य पर एक फ़ंक्शन लागू करने का लाभ भी ले सकते हैं। यदि आप इसे एक सामान्यीकृत समारोह बना

=> (reduce (fn [a k] (update-in a k inc)) {:a 1 :b 2 :c 3 :d 4} [[:a] [:c]]) 
{:a 2, :c 4, :b 2, :d 4} 

कुंजी वैक्टर में संलग्न किया जा करने की जरूरत के बारे में पता हो, लेकिन आप अभी भी मूल अद्यतन की तरह नेस्टेड संरचनाओं में एक से अधिक अद्यतन-इन कर सकते हैं।

, आप स्वचालित रूप से coll ?:

(defn multi-update-in 
    [m v f & args] 
     (reduce 
     (fn [acc p] (apply 
         (partial update-in acc (if (coll? p) p (vector p)) f) 
         args)) m v)) 

जो वैक्टर में कुंजी लपेटकर की आवश्यकता के बिना एकल स्तर/कुंजी अद्यतन के लिए अनुमति होगी के साथ यह परीक्षण से एक चाबी के ऊपर एक वेक्टर लपेट सकता है

=> (multi-update-in {:a 1 :b 2 :c 3 :d 4} [:a :c] inc) 
{:a 2, :c 4, :b 2, :d 4} 

लेकिन अभी भी नेस्ट अपडेट

(def people 
    {"keith" {:age 27 :hobby "needlefelting"} 
    "penelope" {:age 39 :hobby "thaiboxing"} 
    "brian" {:age 12 :hobby "rocket science"}}) 

=> (multi-update-in people [["keith" :age] ["brian" :age]] inc) 
    {"keith" {:age 28, :hobby "needlefelting"}, 
    "penelope" {:age 39, :hobby "thaiboxing"}, 
    "brian" {:age 13, :hobby "rocket science"}} 
0

मैं एक ही विचार के साथ किया गया है करने में सक्षम हो, तो मैं के साथ आया था:

(defn remap 
    "returns a function which takes a map as argument 
    and applies f to each value in the map" 
    [f] 
    #(into {} (map (fn [[k v]] [k (f v)]) %))) 

((remap inc) {:foo 1}) 
;=> {:foo 2} 

या

(def inc-vals (remap inc)) 

(inc-vals {:foo 1}) 
;=> {:foo 2} 
संबंधित मुद्दे