ক্লোজুরে মানচিত্রের মানগুলিতে কোনও ফাংশন ম্যাপিং


138

আমি একই কীগুলির সাথে মানগুলির একটি মানচিত্রকে অন্য মানচিত্রে রূপান্তর করতে চাই তবে মানগুলিতে প্রয়োগ করা একটি ফাংশন দিয়ে। আমি মনে করব ক্লোজুরে এপিআই-তে এটি করার জন্য কোনও ফাংশন ছিল তবে আমি এটি খুঁজে পাইনি।

আমি যা খুঁজছি তার একটি বাস্তবায়ন এখানে

(defn map-function-on-map-vals [m f]
  (reduce (fn [altered-map [k v]] (assoc altered-map k (f v))) {} m))
(println (map-function-on-map-vals {:a "test" :b "testing"} #(.toUpperCase %)))
{:b TESTING, :a TEST}

map-function-on-map-valsইতিমধ্যে বিদ্যমান কি কেউ জানেন ? আমি মনে করি এটি করেছে (সম্ভবত একটি ভাল নাম সহ)।

উত্তর:


153

আমি আপনার reduceসংস্করণ ঠিক আছে। আমি মনে করি এটি মূর্খ। যাইহোক তালিকা অনুধাবন ব্যবহার করে এখানে একটি সংস্করণ's

(defn foo [m f]
  (into {} (for [[k v] m] [k (f v)])))

1
আমি এই সংস্করণটি পছন্দ করি কারণ এটি সমস্ত সংক্ষিপ্ত এবং সুস্পষ্ট আপনি যদি সমস্ত ফাংশন এবং এর ব্যবহারগুলি বুঝতে পারেন তবে। এবং যদি আপনি এটি না শিখেন একটি অজুহাত!
রুনাভাল্ট

আমি রাজী. আমি ফাংশনটি সম্পর্কে জানতাম না, তবে এটি এটি এখানে ব্যবহার করে নিখুঁত করে তোলে।
থমাস

ওহ মানুষ আপনি দেখতে না? আপনি একটি ট্রিট জন্য আছেন। আমি যতবারই সুযোগ পেলাম আমি সেই ফাংশন থেকে দূরে থাকি। তাই শক্তিশালী এবং দরকারী।
রুনাভাল্ট

3
আমি এটি পছন্দ করি, তবে আর্গুমেন্টের আদেশের (প্রশ্ন ছাড়াও) কোনও কারণ আছে কি? আমি mapকোনও কারণে [এফএম] প্রত্যাশা করছিলাম ।
এনএইচ

2
আমি দৃ strongly়ভাবে পরিবর্তে empty} (খালি এম) ব্যবহার করার পরামর্শ দিচ্ছি} সুতরাং এটি মানচিত্রের একটি বিশেষ ধরণের হয়ে থাকবে।
নিকিক

96

আপনি এটি ব্যবহার করতে পারেন clojure.algo.generic.functor/fmap:

user=> (use '[clojure.algo.generic.functor :only (fmap)])
nil
user=> (fmap inc {:a 1 :b 3 :c 5})
{:a 2, :b 4, :c 6}

আমি জানি এই উত্তরগুলি তারিখগুলি দেখতে কিছুটা দেরি হয়েছিল, তবে আমি মনে করি এটি স্পট করে।
এডওয়ার্ডসমেট

এটি কি এটি ক্লোজার 1.3.0 এ পরিণত করেছে?
আনানফায়

13
জেনেরিক.ফানশন লিবি একটি পৃথক গ্রন্থাগারে চলে গেছে: org.clojure/algo.generic "0.1.0" উদাহরণটি এখন পড়তে হবে: (use '[clojure.algo.generic.functor :only (fmap)]) (fmap inc {:a 1 :b 3 :c 5})
ট্র্যাভিস শ্নিবার্গার

2
fmapClojureScript এ কীভাবে পাবেন তা সম্পর্কে কোনও ধারণা ?
sebastibe

37

মানচিত্রকে রূপান্তর করার জন্য এখানে মোটামুটি সাধারণ উপায়। zipmap কীগুলির একটি তালিকা এবং মানগুলির একটি তালিকা নেয় এবং একটি নতুন ক্লোজার মানচিত্র তৈরি করে "সঠিক কাজ করে"। আপনি mapকীগুলি বা উভয়কে পরিবর্তন করতে চারপাশে রাখতে পারেন।

(zipmap (keys data) (map #(do-stuff %) (vals data)))

বা এটি আপনার কার্যক্রমে গুটিয়ে রাখতে:

(defn map-function-on-map-vals [m f]
    (zipmap (keys m) (map f (vals m))))

1
এটি আমাকে বিরক্ত করে যে আমাকে এর জন্য কীগুলি সরবরাহ করতে হবে, তবে এটি প্রদানের জন্য উচ্চ মূল্য নয়। এটি অবশ্যই আমার মূল পরামর্শের চেয়ে অনেক সুন্দর দেখাচ্ছে।
টমাস

1
আমরা কী গ্যারান্টিযুক্ত যে কীগুলি এবং ভালগুলি একই ক্রমে একই মানগুলি ফেরত দেয়? বাছাই করা মানচিত্র এবং হ্যাশ মানচিত্র উভয়ের জন্য?
রব লাচলান

4
রব: হ্যাঁ, কী এবং ভলস সমস্ত মানচিত্রের জন্য একই ক্রম ব্যবহার করবে - মানচিত্রে সিক হিসাবে একই আদেশ order যেহেতু হ্যাশ, বাছাই করা হয়েছে এবং অ্যারে মানচিত্রগুলি সমস্ত অপরিবর্তনীয় তাই গড় সময়ে অর্ডার পরিবর্তনের কোনও সম্ভাবনা নেই।
চৌসর

2
এটি ক্ষেত্রে বলে মনে হয় তবে এটি কি কোথাও নথিভুক্ত করা হয়েছে? কমপক্ষে কী এবং ভ্যালসগুলির জন্য ডকাস্ট্রিংগুলি এটি উল্লেখ করতে ব্যর্থ। আমি এটি ব্যবহার করতে আরও স্বাচ্ছন্দ্যবোধ করব যদি আমি কিছু অফিসিয়াল ডকুমেন্টেশনগুলিতে ইঙ্গিত করতে পারি যে এটি কাজ করে যাচ্ছে বলে প্রতিশ্রুতি দেয়।
জৌনি কে। সেপ্পেনেন

1
@ জেসন হ্যাঁ, তারা এটিকে দস্তাবেজগুলিতে ১.6 সংস্করণে যুক্ত করেছেন I dev.clojure.org/jira/browse/CLJ-1302
কে। সেপ্পেনেন

23

ক্লোজার কুকবুক থেকে নেওয়া, এখানে হ্রাস-কেভি রয়েছে:

(defn map-kv [m f]
  (reduce-kv #(assoc %1 %2 (f %3)) {} m))

8

এটি করার জন্য এখানে মোটামুটি মূর্তিমান পদ্ধতি:

(defn map-function-on-map-vals [m f]
        (apply merge
               (map (fn [[k v]] {k (f v)})
                    m)))

উদাহরণ:

user> (map-function-on-map-vals {1 1, 2 2, 3 3} inc))
{3 4, 2 3, 1 2}

2
তাহলে এটা স্পষ্ট নয়: বেনামা ফাংশন destructures চাবিকাঠি এবং মান এবং V এবং তারপর একটি হ্যাশ মানচিত্রে ম্যাপিং ফেরৎ করার (FV)
সিদ্ধার্থ রেড্ডি

6

map-map, map-map-keysএবংmap-map-values

আমি এটির জন্য ক্লোজরে বিদ্যমান কোন কার্যকারিতা সম্পর্কে জানি না, তবে আপনি এখানে map-map-valuesঅনুলিপি করতে পারেন এমন ফাংশনটির একটি বাস্তবায়ন এখানে । এটি দুটি ঘনিষ্ঠভাবে সম্পর্কিত ফাংশন নিয়ে আসে map-mapএবং map-map-keysএটি স্ট্যান্ডার্ড লাইব্রেরি থেকেও হারিয়ে যায়:

(defn map-map
    "Returns a new map with each key-value pair in `m` transformed by `f`. `f` takes the arguments `[key value]` and should return a value castable to a map entry, such as `{transformed-key transformed-value}`."
    [f m]
    (into (empty m) (map #(apply f %) m)) )

(defn map-map-keys [f m]
    (map-map (fn [key value] {(f key) value}) m) )

(defn map-map-values [f m]
    (map-map (fn [key value] {key (f value)}) m) )

ব্যবহার

আপনি map-map-valuesএই মত কল করতে পারেন :

(map-map-values str {:a 1 :b 2})
;;           => {:a "1", :b "2"}

এবং অন্যান্য দুটি ফাংশন এর মতো:

(map-map-keys str {:a 1 :b 2})
;;         => {":a" 1, ":b" 2}
(map-map (fn [k v] {v k}) {:a 1 :b 2})
;;    => {1 :a, 2 :b}

বিকল্প বাস্তবায়ন

আপনি যদি কেবলমাত্র map-map-keysবা map-map-valuesআরও সাধারণ map-mapক্রিয়াকলাপ ছাড়া চান , আপনি এই প্রয়োগগুলি ব্যবহার করতে পারেন, যা নির্ভর করে না map-map:

(defn map-map-keys [f m]
    (into (empty m)
        (for [[key value] m]
            {(f key) value} )))

(defn map-map-values [f m]
    (into (empty m)
        (for [[key value] m]
            {key (f value)} )))

এছাড়াও, এখানে বিকল্প বিকল্প বাস্তবায়নের পরিবর্তে এর map-mapউপর ভিত্তি করে clojure.walk/walkতৈরি করা হয় into, যদি আপনি এই শব্দবন্ধটিকে পছন্দ করেন:

(defn map-map [f m]
    (clojure.walk/walk #(apply f %) identity m) )

পেরেলেল সংস্করণ - pmap-mapইত্যাদি

আপনার যদি প্রয়োজন হয় তবে এই ফাংশনগুলির সমান্তরাল সংস্করণ রয়েছে। তারা কেবল pmapপরিবর্তে ব্যবহার করুন map

(defn pmap-map [f m]
    (into (empty m) (pmap #(apply f %) m)) )
(defn pmap-map-keys [f m]
    (pmap-map (fn [key value] {(f key) value}) m) )
(defn pmap-map-values [f m]
    (pmap-map (fn [key value] {key (f value)}) m) )

1
প্রাইমেটিক্স ম্যাপ-ভ্যালস ফাংশনও পরীক্ষা করে দেখুন। এটি দ্রুতগামী github.com/Prismatic/plumbing/blob/…
ClojureMostly

2

আমি ক্লোজার ন00 বি, তাই আরও অনেক সুন্দর সমাধান হতে পারে। এখানে আমার:

(def example {:a 1 :b 2 :c 3 :d 4})
(def func #(* % %))

(prn example)

(defn remap [m f]
  (apply hash-map (mapcat #(list % (f (% m))) (keys m))))

(prn (remap example func))

আনোন ফানক প্রতিটি কী এবং এর মূল্যবান মান থেকে কিছুটা 2-তালিকা তৈরি করে। ম্যাপক্যাট এই ফাংশনটি মানচিত্রের কীগুলির ক্রম অনুসারে চালিত করে এবং সম্পূর্ণ কাজকে একটি বড় তালিকার সাথে যুক্ত করে। "প্রয়োগ হ্যাশ-মানচিত্র" সেই ক্রম থেকে একটি নতুন মানচিত্র তৈরি করে। (% মি )টিকে কিছুটা অদ্ভুত লাগতে পারে, সম্পর্কিত মানটি দেখার জন্য মানচিত্রে একটি চাবি প্রয়োগ করার জন্য এটি বুদ্ধিমান ক্লোজার।

সর্বাধিক উচ্চ প্রস্তাবিত পাঠ: ক্লোজার চিট শিট


আমি যেমন আপনার উদাহরণে করেছি তেমন গর্তের অনুক্রমগুলি সম্পর্কে ভেবেছিলাম। আপনার নামটি আমার নিজের চেয়ে অনেক বেশি ফাংশন করতেও পছন্দ করি :)
টমাস

ক্লোজুরে, কীওয়ার্ডগুলি এমন ক্রিয়াকলাপ যা সেগুলিকে যা কিছু ক্রম প্রবাহিত হয় সেগুলিতে নিজেকে দেখায়। এজন্য (: কীওয়ার্ড এ-ম্যাপ) কাজ করে। তবে কীটি কীওয়ার্ড না থাকলে কোনও মানচিত্রে নিজেকে সন্ধান করার জন্য কীটি কোনও ফাংশন হিসাবে ব্যবহার করা কার্যকর হবে না। সুতরাং আপনি উপরের (% m) (m%) এ পরিবর্তন করতে চাইতে পারেন যা কী কী তা বিবেচনা করেই কাজ করবে।
সিদ্ধার্থ রেড্ডি

ওহো! টিপটির জন্য ধন্যবাদ, সিদ্ধার্থ!
কার্ল স্মট্রিক্জ

2
(defn map-vals
  "Map f over every value of m.
   Returns a map with the same keys as m, where each of its values is now the result of applying f to them one by one.
   f is a function of one arg, which will be called which each value of m, and should return the new value.
   Faster then map-vals-transient on small maps (8 elements and under)"
  [f m]
  (reduce-kv (fn [m k v]
               (assoc m k (f v)))
             {} m))

(defn map-vals-transient
  "Map f over every value of m.
   Returns a map with the same keys as m, where each of its values is now the result of applying f to them one by one.
   f is a function of one arg, which will be called which each value of m, and should return the new value.
   Faster then map-vals on big maps (9 elements or more)"
  [f m]
  (persistent! (reduce-kv (fn [m k v]
                            (assoc! m k (f v)))
                          (transient {}) m)))

1

আমি তোমার reduceসংস্করণ পছন্দ করি খুব সামান্য প্রকরণের সাথে এটি রেকর্ড কাঠামোর ধরণও ধরে রাখতে পারে:

(defn map-function-on-map-vals [m f]
  (reduce (fn [altered-map [k v]] (assoc altered-map k (f v))) m m))

দ্বারা {}প্রতিস্থাপিত হয়েছিল m। এই পরিবর্তনের সাথে, রেকর্ডগুলি রেকর্ডগুলি থেকে যায়:

(defrecord Person [firstname lastname])

(def p (map->Person {}))
(class p) '=> Person

(class (map-function-on-map-vals p
  (fn [v] (str v)))) '=> Person

শুরু করে {}, রেকর্ডটি তার রেকর্ডনেস হারিয়ে ফেলে , যা আপনি ধরে রাখতে চান, যদি আপনি রেকর্ডের ক্ষমতাগুলি চান (উদাহরণস্বরূপ কমপ্যাক্ট মেমরির উপস্থাপনা)।


0

আমি ভাবছি কেন এখনও কেউ স্পেকটার লাইব্রেরির উল্লেখ করেনি। এই ধরণের রূপান্তরটি কোডে সহজ করার জন্য রচনা করা হয়েছে (এবং আরও গুরুত্বপূর্ণ, লিখিত কোডটি সহজে বোঝা সহজ), যদিও এখনও খুব পারফরম্যান্ট রয়েছেন:

(require '[com.rpl.specter :as specter])

(defn map-vals [m f]
  (specter/transform
   [specter/ALL specter/LAST]
   f m))

(map-vals {:a "test" :b "testing"}
          #(.toUpperCase %))

খাঁটি ক্লোজারে এই জাতীয় ফাংশনটি লেখা সহজ, তবে আপনি বিভিন্ন ডেটা স্ট্রাকচারের সমন্বয়ে অত্যন্ত নেস্টেড কোডে চলে গেলে কোডটি আরও জটিল হয়। এবং এই যেখানে স্পেকটার আসে।

আমি পর্যবেক্ষক সুপারিশ এই পর্বের যা প্রেরণা পিছনে এবং বিবরণ ব্যাখ্যা Clojure টিভিতে ভূত


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.