2013-06-26 10 views
9

मैं मुसीबत निम्नलिखित समस्या का समाधान खोजने आ रही हैं:मर्ज दो जटिल डेटा संरचनाओं

चलें कहते हैं कि मैं एक नक्शा है:

(def defaults { 
    :name "John" 
    :surname "Doe" 
    :info {:date-of-birth "01-01-1980" 
      :registered [{:type "newsletter" :name "breaking news" }]} 
}) 

और फिर मैं एक ऐसी ही संरचित नक्शा पारित लेकिन मैं चाहता हूँ वैक्टर एकत्रित होना और चाबी के बाकी के ऊपर लिख:

(def new { 
    :name "Peter" 
    :info {:date-of-birth "11-01-1986" 
      :registered [{:type "alert" :name "mobile-alert" }]} 
}) 

और मैं इस परिणाम हैं:

{:name "Peter" 
    :surname "Doe" 
    :info {:date-of-birth "11-01-1986" 
      :registered [{:type "newsletter" :name "breaking news" } 
          {:type "alert"  :name "mobile-alert" }]}} 

अब मैं की तरह स्थिर वाक्य रचना का उपयोग करके आसानी से कर सकते हैं:

(reduce conj (get-in defaults [:info :registered]) (get-in new [:info :registered])) 

(शायद एक बेहतर तरीका नहीं है ...) लेकिन मैं निम्नलिखित गुणों के साथ एक गतिशील समारोह की अधिक उम्मीद थी:

  1. सही नक्शा
  2. से संरचना मूल्यों के साथ किसी भी कुंजी जानने
  3. अद्यतन के बिना, दोनों नक्शे से सभी चाबियाँ रखें कि यदि एक कुंजी के वैल एक वेक्टर,है तो 013,210 सही नक्शा वेक्टर के साथ वेक्टर (उचित कुंजी निश्चित रूप से मौजूद रहने पर) पहले से मदद के लिए

धन्यवाद :)

उत्तर

20

आपको निश्चित रूप से merge-with फ़ंक्शन देखना चाहिए। यह संभव कार्यान्वयन है:

(defn deep-merge [a b] 
    (merge-with (fn [x y] 
       (cond (map? y) (deep-merge x y) 
         (vector? y) (concat x y) 
         :else y)) 
       a b)) 
+0

+1 पूरी तरह से 'विलय-साथ' के बारे में भूल गया। –

+0

पूरी तरह से काम करता है। मुझे संदेह था कि इसमें विलय के साथ कुछ करना था लेकिन मैं इसे समझ नहीं पाया ... चीयर्स! –

0

यहाँ कार्यक्षमता के इस प्रकार के लिए एक संभावित कार्यान्वयन है। यह कम से कम एक शुरुआती बिंदु है, आपको अपने डेटा की संभावित संरचना के आधार पर कुछ अतिरिक्त सत्यापन की आवश्यकता हो सकती है (उदाहरण के लिए यदि ओवरराइडिंग मानचित्र का मूल्य वेक्टर है लेकिन डिफ़ॉल्ट मानचित्र में मान भी संग्रह नहीं है?)।

(declare merge-maps) 

(defn merge-map [x [k v]] 
    (cond (vector? v) 
      (assoc x k (vec (reduce conj (x k) v))) 
     (map? v) 
      (assoc x k (merge-maps (x k) v)) 
     :esle 
      (assoc x k v))) 

(defn merge-maps [x y] 
    (reduce merge-map x y)) 

(merge-maps defaults new) 

;= {:info {:date-of-birth "11-01-1986", 
;=   :registered [{:name "breaking news", :type "newsletter"} 
;=      {:name "mobile-alert", :type "alert"}]}, 
;= :name "Peter", 
;= :surname "Doe"} 
संबंधित मुद्दे