2011-09-02 10 views
8

में एक हैश मानचित्र को अंदर घुमाएं मैं क्लोजर के लिए बहुत नया हूं और क्लोजर गुरु के लिए एक दिलचस्प समस्या है। मैं "प्रोग्रामिंग कलेक्टिव इंटेलिजेंस" पुस्तक के माध्यम से काम कर रहा हूं और क्लोजर में उदाहरणों को कोड करने की कोशिश कर रहा हूं (पुस्तक में उन्हें पाइथन में शामिल है)। पहले अध्याय में हमारे पास फिल्म आलोचकों का एक हैश मैप सेटअप और विभिन्न फिल्मों को दी गई रैंकिंग है। ऐसा लगता है:क्लोजर

{"Lisa Rose" {"Lady in the Water" 2.5, "Snakes on a Plane" 3.5 }, 
"Gene Seymour" {"Lady in the Water" 3.0, "Snakes on a Plane" 3.5}} 

समस्या यह है। कैसे है कि अंदर बाहर बारी करने के लिए इतना है कि मैं एक हैश नक्शा है कि इस तरह दिखता है मिलती है:

{"Lady in the Water" {"Lisa Rose" 2.5, "Gene Seymour" 3.0}, 
"Snakes on a Plane" {"Lisa Rose" 3.5, "Gene Seymour" 3.5}} 

क्या यह पूरा करने के अपने कार्य किया जाएगा?

+0

उत्कृष्ट उत्तरों के लिए धन्यवाद। मैंने उन सभी से कुछ सीखा। –

उत्तर

17
(let [m {"Lisa Rose" {"Lady in the Water" 2.5, "Snakes on a Plane" 3.5 }, 
     "Gene Seymour" {"Lady in the Water" 3.0, "Snakes on a Plane" 3.5}}] 
    (apply merge-with merge 
     (for [[ok ov] m 
       [ik iv] ov] 
      {ik {ok iv}}))) 

{"Snakes on a Plane" {"Gene Seymour" 3.5, "Lisa Rose" 3.5}, 
"Lady in the Water" {"Gene Seymour" 3.0, "Lisa Rose" 2.5}} 
+0

मेरे [प्रश्न] (http://stackoverflow.com/q/23651045/813665) को डुप्लिकेट के रूप में चिह्नित करने के लिए धन्यवाद। क्या आपको लगता है कि 'मर्ज-साथ' के लिए 'conj' या' merge' का उपयोग करना बेहतर है? – viebel

+0

@ विएबेल मैं 'मर्ज' पसंद करता हूं।मुझे अजीब तथ्य पर भरोसा करना पसंद नहीं है कि नक्शे के लिए, 'conj' 'in' के बराबर है - मैं यह दिखाता हूं कि' conj' केवल नक्शा प्रविष्टियों को स्वीकार करता है। – amalloy

3

मैं निम्नलिखित का प्रस्ताव कर सकता हूं: हमारे पास नक्शा - प्रविष्टियों का संग्रह है। प्रत्येक प्रविष्टि

{:Lisa {:Lady 2.5, :Snakes 3.5}, 
:Gene {:Lady 3.0, :Snakes 3.5}} 

उलटा:

([:Lady {:Lisa 2.5}], [:Snakes {:Lisa 3.5}]) 
([:Lady {:Gene 3.0}], [:Snakes {:Gene 3.5}]) 

उन्हें Concat: अंदर बाहर हर प्रविष्टि देते हैं और उन्हें उन्हें मर्ज: प्रारंभिक

([:Lady {:Lisa 2.5}], [:Snakes {:Lisa 3.5}], [:Lady {:Gene 3.0}], [:Snakes {:Gene 3.5}]) 

और उनमें से एक नक्शा करने के लिए उन्हें मर्ज:

{:Lady {:Lisa 2.5, :Gene 3.0}, 
:Snakes {:Lisa 3.5, :Gene 3.5}} 

कोड:

(defn inverse-map [m] 
     (let [inverse-entry (fn [[name movies]] 
           (map (fn [[movie rating]] 
             [movie {name rating}]) 
            movies))] 
      (->> (map inverse-entry m) 
       (reduce concat) 
       (reduce (fn [res [movie entry]] 
          (update-in res [movie] merge entry)) 
         {})))) 

तो हम नक्शा मिलता है, (यह वैक्टर का संग्रह है [कुंजी मान]), उलटा प्रत्येक प्रविष्टि (वेक्टर [कुंजी मान])। अब हमारे पास वैक्टरों के संग्रह का संग्रह है, उन्हें एक संग्रह में शामिल करें। और अंत में, कम करने का उपयोग करके हम मानचित्र में हर वेक्टर जोड़ते हैं।

मुझे लगता है कि और अधिक सुरुचिपूर्ण समाधान है, लेकिन मेरा भी काम करता है।

6
(defn inverse-map [m] 
    (let [inner-keys (-> m first val keys) 
     outer-keys (keys m)] 
    (apply merge-with merge 
      (for [ik inner-keys 
       ok outer-keys] 
      {ik {ok (get-in input [ok ik])}})))) 

यह मानता है कि आंतरिक नक्शे में रुचि के सभी कुंजी पहले आंतरिक मानचित्र पर मौजूद हैं। यदि यह गलत है, तो (-> m first val keys) को ब्याज की सभी कुंजियों के संग्रह को वापस करने वाले कुछ के साथ प्रतिस्थापित करना होगा, उदा। (->> m (map values) (mapcat keys))

विचार {inner-key {outer-key the-value-at-inner-key-in-the-map-at-outer-key}} फ़ॉर्म का नक्शा बनाना है, फिर उन्हें उचित रूप से एक साथ मिलाएं।

प्रश्न टेक्स्ट में मानचित्र पर वापसी मूल्य निर्दिष्ट है।

अब, उपरोक्त कई मध्यवर्ती संरचनाएं बनाता है, जो प्रदर्शन-योग्य समस्या हो सकती है। गति का ही महत्व है, तो आप के लिए loop और यात्रियों स्विच कर सकते हैं:

(defn transient-inverse-map [m] 
    (let [inner-keys (-> m first val keys) 
     outer-keys (keys m) 
     t (transient {})] 
    (loop [inner-keys inner-keys 
      t t] 
     (if (seq inner-keys) 
     (recur (next inner-keys) 
       (assoc! t ik 
         (let [ik (first inner-keys) 
          t (transient {})] 
         (loop [outer-keys outer-keys 
           t t] 
          (if (seq outer-keys) 
          (let [ok (first outer-keys)] 
           (recur (next outer-keys) 
             (assoc! t ok (get-in m [ok ik])))) 
          (persistent! t)))))) 
     (persistent! t))))) 

विचार एक ही है, कठिन है, तो कोड से विचार करने के लिए।