Re: Transforming map entries
I have a couple utility functions I use a lot for creating maps from sequences and transforming one map to another. These are (poorly) named mapmap and mapmapmap. (Yes I know the names are awful but I have lived with them long enough that they've stuck.) mapmap takes a key production function (optional - uses identity by default), a value production function, and a source sequence. (def c (range 5)) (mapmap #(+ 1 %) #(* 2 %) c) -> {5 8, 4 6, 3 4, 2 2, 1 0} More here: http://tech.puredanger.com/2010/09/24/meet-my-little-friend-mapmap/ mapmapmap is similar but takes a map, not a sequence. It applies the key function to transform the keys and the value function to transform the values. So your request would be: (mapmapmap #(if (string? %) (upper-case %) %) mymap) Here's a gist with the definition of both: https://gist.github.com/843292 Hope you find it useful... Alex On Feb 21, 9:08 pm, yair wrote: > I'm hoping this is a dumb question and I've missed something obvious. > I have a map with various key-value pairs and I want to transform some > of the values, e.g. > > (def mymap {:first "john" :last "smith" :age 25}) and say I want to > change the strings to be upper case. > Right now all I can think of doing is using reduce and passing in an > empty map and the re-associating each key with the (possibly) > transformed value. Is there something like the map function that > takes two parameters, one a function that receives a pair and returns > a new pair, and the other a map, and returns a map that's > reconstituted from those pairs? > > Thanks -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
Reduce! (reduce (fn [new-map [key value]] (assoc new-map ...)) {} old-map) This is nice because you can change both keys and values, even add or remove keys. For something simpler: (into {} (fn [[key value]] ... ) old-map) -Stuart Sierra clojure.com -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
That is true. Thank you for the reminder. On Feb 23, 10:18 am, Laurent PETIT wrote: > 2011/2/23 Benny Tsai > > > My guess is that Clojure's fmap behaves that way because it is modeled > > Note that it's not "Clojure's fmap". > fmap is a function in a clojure contrib namespace. > > The distinction may be important. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
On Wed, Feb 23, 2011 at 11:55 AM, Benny Tsai wrote: > My guess is that Clojure's fmap behaves that way because it is modeled > after Haskell's fmap Hmm, I thought it might be a Haskell thing. > To pass both keys and values to your transforming function, I think > Alan's idea of using 'walk' is the best: > > (use '[clojure.walk :only (walk)]) > > (def my-map {:first "john" :last "smith" :age 25}) > > (defn my-fn [[key value]] > (if (string? value) > [key (.toUpperCase value)] > [key value])) > > user=> (walk my-fn identity my-map) > {:first "JOHN", :last "SMITH", :age 25} That looks pretty nice. I'll give that a shot, thanks. > > On Feb 23, 6:27 am, Chris Maier wrote: >> Can anybody explain why fmap, when operating on an IPersistentMap, >> only passes the function the value of the map entry, instead of the >> entire map entry (i.e., the key and value pair)? It seems a bit odd >> in that all the other implementations of fmap operate on the entire >> item in the sequence. Also, I can imagine cases where you'd want to >> do some map transformation that also depends on the key (do something >> for entries A, B, and C, but something else for entries X, Y, and Z). >> >> I suppose I could use remove-method and then write my own fmap >> implementation for IPersistentMap. I'm curious about the design, >> though. >> >> Thanks, >> Chris >> >> >> >> >> >> >> >> On Tue, Feb 22, 2011 at 6:56 PM, Benny Tsai wrote: >> > There is fmap from clojure.contrib.generic.functor, which expects a >> > function of arity 1, for just the value: >> >> > (use 'clojure.contrib.generic.functor) >> > (require '[clojure.string :as str]) >> >> > (def my-map {:first "john" :last "smith" :age 25}) >> >> > (defn my-fn [value] >> > (if (string? value) >> > (str/upper-case value) >> > value)) >> >> > user=> (fmap my-fn my-map) >> > {:first "JOHN", :last "SMITH", :age 25} >> >> > On Feb 22, 4:23 pm, rob levy wrote: >> >> The usual intuitive options for this are reduce, zipmap, or into. You can >> >> also write a lazily recursive solution. I wonder why there's no function >> >> in >> >> core that lazily re-constructs the map with the results of the function? >> >> It >> >> seems to have been discussed on the list at least once or twice. It seems >> >> like there would have to be two versions of it, one expecting a function >> >> with an arity of one (for just the value) and another expecting an arity >> >> of >> >> two (key and value). >> >> >> On Mon, Feb 21, 2011 at 10:08 PM, yair wrote: >> >> > I'm hoping this is a dumb question and I've missed something obvious. >> >> > I have a map with various key-value pairs and I want to transform some >> >> > of the values, e.g. >> >> >> > (def mymap {:first "john" :last "smith" :age 25}) and say I want to >> >> > change the strings to be upper case. >> >> > Right now all I can think of doing is using reduce and passing in an >> >> > empty map and the re-associating each key with the (possibly) >> >> > transformed value. Is there something like the map function that >> >> > takes two parameters, one a function that receives a pair and returns >> >> > a new pair, and the other a map, and returns a map that's >> >> > reconstituted from those pairs? >> >> >> > Thanks >> >> >> > -- >> >> > You received this message because you are subscribed to the Google >> >> > Groups "Clojure" group. >> >> > To post to this group, send email to clojure@googlegroups.com >> >> > Note that posts from new members are moderated - please be patient with >> >> > your first post. >> >> > To unsubscribe from this group, send email to >> >> > clojure+unsubscr...@googlegroups.com >> >> > For more options, visit this group at >> >> >http://groups.google.com/group/clojure?hl=en >> >> > -- >> > You received this message because you are subscribed to the Google >> > Groups "Clojure" group. >> > To post to this group, send email to clojure@googlegroups.com >> > Note that posts from new members are moderated - please be patient with >> > your first post. >> > To unsubscribe from this group, send email to >> > clojure+unsubscr...@googlegroups.com >> > For more options, visit this group at >> >http://groups.google.com/group/clojure?hl=en > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with your > first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, v
Re: Transforming map entries
2011/2/23 Benny Tsai > My guess is that Clojure's fmap behaves that way because it is modeled > Note that it's not "Clojure's fmap". fmap is a function in a clojure contrib namespace. The distinction may be important. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
My guess is that Clojure's fmap behaves that way because it is modeled after Haskell's fmap, which only accepts functions that operate only on the values due to the way fmap (and the Functor typeclass that fmap belongs to) is modeled in Haskell's type system. To pass both keys and values to your transforming function, I think Alan's idea of using 'walk' is the best: (use '[clojure.walk :only (walk)]) (def my-map {:first "john" :last "smith" :age 25}) (defn my-fn [[key value]] (if (string? value) [key (.toUpperCase value)] [key value])) user=> (walk my-fn identity my-map) {:first "JOHN", :last "SMITH", :age 25} On Feb 23, 6:27 am, Chris Maier wrote: > Can anybody explain why fmap, when operating on an IPersistentMap, > only passes the function the value of the map entry, instead of the > entire map entry (i.e., the key and value pair)? It seems a bit odd > in that all the other implementations of fmap operate on the entire > item in the sequence. Also, I can imagine cases where you'd want to > do some map transformation that also depends on the key (do something > for entries A, B, and C, but something else for entries X, Y, and Z). > > I suppose I could use remove-method and then write my own fmap > implementation for IPersistentMap. I'm curious about the design, > though. > > Thanks, > Chris > > > > > > > > On Tue, Feb 22, 2011 at 6:56 PM, Benny Tsai wrote: > > There is fmap from clojure.contrib.generic.functor, which expects a > > function of arity 1, for just the value: > > > (use 'clojure.contrib.generic.functor) > > (require '[clojure.string :as str]) > > > (def my-map {:first "john" :last "smith" :age 25}) > > > (defn my-fn [value] > > (if (string? value) > > (str/upper-case value) > > value)) > > > user=> (fmap my-fn my-map) > > {:first "JOHN", :last "SMITH", :age 25} > > > On Feb 22, 4:23 pm, rob levy wrote: > >> The usual intuitive options for this are reduce, zipmap, or into. You can > >> also write a lazily recursive solution. I wonder why there's no function > >> in > >> core that lazily re-constructs the map with the results of the function? > >> It > >> seems to have been discussed on the list at least once or twice. It seems > >> like there would have to be two versions of it, one expecting a function > >> with an arity of one (for just the value) and another expecting an arity of > >> two (key and value). > > >> On Mon, Feb 21, 2011 at 10:08 PM, yair wrote: > >> > I'm hoping this is a dumb question and I've missed something obvious. > >> > I have a map with various key-value pairs and I want to transform some > >> > of the values, e.g. > > >> > (def mymap {:first "john" :last "smith" :age 25}) and say I want to > >> > change the strings to be upper case. > >> > Right now all I can think of doing is using reduce and passing in an > >> > empty map and the re-associating each key with the (possibly) > >> > transformed value. Is there something like the map function that > >> > takes two parameters, one a function that receives a pair and returns > >> > a new pair, and the other a map, and returns a map that's > >> > reconstituted from those pairs? > > >> > Thanks > > >> > -- > >> > You received this message because you are subscribed to the Google > >> > Groups "Clojure" group. > >> > To post to this group, send email to clojure@googlegroups.com > >> > Note that posts from new members are moderated - please be patient with > >> > your first post. > >> > To unsubscribe from this group, send email to > >> > clojure+unsubscr...@googlegroups.com > >> > For more options, visit this group at > >> >http://groups.google.com/group/clojure?hl=en > > > -- > > You received this message because you are subscribed to the Google > > Groups "Clojure" group. > > To post to this group, send email to clojure@googlegroups.com > > Note that posts from new members are moderated - please be patient with > > your first post. > > To unsubscribe from this group, send email to > > clojure+unsubscr...@googlegroups.com > > For more options, visit this group at > >http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
And at the underkill end of the spectrum :) (comp #(.toUpperCase %) mymap) (Seriously: might be feasible of you don't need the map properties afterwards...) Sincerely Meikel -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
Perhaps this is an overkill, but it comes to my mind :) (I'm new to clojure) user=> (def mymap {:a (ref "foo") :b (ref "bar")}) #'user/mymap user=> mymap {:a #, :b #} user=> (map #(dosync (ref-set %1 (repeat 2 (deref %1 (vals mymap)) (("foo" "foo") ("bar" "bar")) user=> mymap {:a #, :b #} Stanislav Paskalev On Wed, Feb 23, 2011 at 1:27 AM, Nurullah Akkaya wrote: > You can use map to get your new sequence of pairs, the turn it into a > hash-map using into, > > (->> {:first "john" :last "smith" :age 25} > (map #(let [[k v] %] > (if (string? v) > [k (.toUpperCase v)] [k v]))) > (into {})) > > Best, > -- > Nurullah Akkaya > http://nakkaya.com > On Tuesday, February 22, 2011 at 5:08 AM, yair wrote: >> I'm hoping this is a dumb question and I've missed something obvious. >> I have a map with various key-value pairs and I want to transform some >> of the values, e.g. >> >> (def mymap {:first "john" :last "smith" :age 25}) and say I want to >> change the strings to be upper case. >> Right now all I can think of doing is using reduce and passing in an >> empty map and the re-associating each key with the (possibly) >> transformed value. Is there something like the map function that >> takes two parameters, one a function that receives a pair and returns >> a new pair, and the other a map, and returns a map that's >> reconstituted from those pairs? >> >> Thanks >> >> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clojure@googlegroups.com >> Note that posts from new members are moderated - please be patient with your >> first post. >> To unsubscribe from this group, send email to >> clojure+unsubscr...@googlegroups.com >> For more options, visit this group at >> http://groups.google.com/group/clojure?hl=en >> > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with your > first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
Can anybody explain why fmap, when operating on an IPersistentMap, only passes the function the value of the map entry, instead of the entire map entry (i.e., the key and value pair)? It seems a bit odd in that all the other implementations of fmap operate on the entire item in the sequence. Also, I can imagine cases where you'd want to do some map transformation that also depends on the key (do something for entries A, B, and C, but something else for entries X, Y, and Z). I suppose I could use remove-method and then write my own fmap implementation for IPersistentMap. I'm curious about the design, though. Thanks, Chris On Tue, Feb 22, 2011 at 6:56 PM, Benny Tsai wrote: > There is fmap from clojure.contrib.generic.functor, which expects a > function of arity 1, for just the value: > > (use 'clojure.contrib.generic.functor) > (require '[clojure.string :as str]) > > (def my-map {:first "john" :last "smith" :age 25}) > > (defn my-fn [value] > (if (string? value) > (str/upper-case value) > value)) > > user=> (fmap my-fn my-map) > {:first "JOHN", :last "SMITH", :age 25} > > On Feb 22, 4:23 pm, rob levy wrote: >> The usual intuitive options for this are reduce, zipmap, or into. You can >> also write a lazily recursive solution. I wonder why there's no function in >> core that lazily re-constructs the map with the results of the function? It >> seems to have been discussed on the list at least once or twice. It seems >> like there would have to be two versions of it, one expecting a function >> with an arity of one (for just the value) and another expecting an arity of >> two (key and value). >> >> >> >> >> >> >> >> On Mon, Feb 21, 2011 at 10:08 PM, yair wrote: >> > I'm hoping this is a dumb question and I've missed something obvious. >> > I have a map with various key-value pairs and I want to transform some >> > of the values, e.g. >> >> > (def mymap {:first "john" :last "smith" :age 25}) and say I want to >> > change the strings to be upper case. >> > Right now all I can think of doing is using reduce and passing in an >> > empty map and the re-associating each key with the (possibly) >> > transformed value. Is there something like the map function that >> > takes two parameters, one a function that receives a pair and returns >> > a new pair, and the other a map, and returns a map that's >> > reconstituted from those pairs? >> >> > Thanks >> >> > -- >> > You received this message because you are subscribed to the Google >> > Groups "Clojure" group. >> > To post to this group, send email to clojure@googlegroups.com >> > Note that posts from new members are moderated - please be patient with >> > your first post. >> > To unsubscribe from this group, send email to >> > clojure+unsubscr...@googlegroups.com >> > For more options, visit this group at >> >http://groups.google.com/group/clojure?hl=en > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with your > first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
On Feb 22, 4:08 am, yair wrote: > I'm hoping this is a dumb question and I've missed something obvious. > I have a map with various key-value pairs and I want to transform some > of the values, e.g. > > (def mymap {:first "john" :last "smith" :age 25}) and say I want to > change the strings to be upper case. > Right now all I can think of doing is using reduce and passing in an > empty map and the re-associating each key with the (possibly) > transformed value. Is there something like the map function that > takes two parameters, one a function that receives a pair and returns > a new pair, and the other a map, and returns a map that's > reconstituted from those pairs? since hash-maps aren't lazy, what's wrong with using hash-map? (apply hash-map (mapcat (fn [[k v]] [(.toUpperCase k) v]) {"bla" 1 "bloop" 2}) ) => {"BLOOP" 2, "BLA" 1} or: -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
On Tue, 22 Feb 2011 16:23:00 -0800 (PST) Alan wrote: > Yes, it is guaranteed, and I'm dubious about your claim about > serializing. (seq foo) will return the entries in foo in the same > order always; but (seq (assoc foo 1 2)) may return the entries in a > completely different order. You can treat (keys x) as if it were > defined by (map key (seq x)): References please? There was a discussion a while back about why maps weren't treated as sequences, the gist of it being that (seq somemap) wasn't guaranteed to always return things in the same order, and requiring an explicit conversion was a reminder of that. Given that, the fact that (keys x) can be treated the same as (map key (seq x)) isn't sufficient to guarantee that (keys x) and (vals x) will return things in the proper order to zipmap them. Given that it was an email discussion, it could well have been wrong - or things could have changed since then. But I'd like to see a reference to that effect, other than the fact that the current implementation behaves that way. Thanks, http://www.mired.org/consulting.html Independent Software developer/SCM consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
On Tue, Feb 22, 2011 at 7:36 PM, Daniel Bell wrote: > I don't know if it's specified in the documentation anywhere It doesn't seem to be. > but > (= map-I-made-up > (zipmap > (keys map-I-made-up) > (vals map-I-made-up))) > > returns true. However, it is clearly intentional behavior nonetheless. In particular, I can think of no other reason why "keys" doesn't return a set than to avoid potential reordering; so (zipmap (keys m) (map do-something-to (vals m))) and things like that will work properly. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
I don't know if it's specified in the documentation anywhere, but (= map-I-made-up (zipmap (keys map-I-made-up) (vals map-I-made-up))) returns true. On Feb 22, 5:17 pm, Mike Meyer wrote: > On Tue, 22 Feb 2011 15:36:02 -0800 (PST) > > Daniel Bell wrote: > > I can't think of anything core, but > > > (let [f #(. % toUpperCase)] > > (zipmap (keys skills) (map f (vals skills doesn't seem too bad. > > Does clojure guarantee that keys & vals return things in the proper > order for this to work? Since it doesn't guarantee that serializing > the entries of a map will always get the same order, that seems > unlikely. > > thanks, > -- > Mike Meyer http://www.mired.org/consulting.html > Independent Software developer/SCM consultant, email for more information. > > O< ascii ribbon campaign - stop html mail -www.asciiribbon.org -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
On Tue, Feb 22, 2011 at 7:26 PM, Benny Tsai wrote: > I was introduced to fmap by Haskell. Specifically, the (IMHO) most > excellent "Learn You a Haskell for Great Good!" online tutorial. > Highly recommended! Take off every 'monad'! For great justice! -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
I was introduced to fmap by Haskell. Specifically, the (IMHO) most excellent "Learn You a Haskell for Great Good!" online tutorial. Highly recommended! On Feb 22, 5:04 pm, rob levy wrote: > Yeah, fmap is perfect and definitely the most elegant for the specific > problem described by the OP. I had never heard of that one. > > > > > > > > On Tue, Feb 22, 2011 at 6:56 PM, Benny Tsai wrote: > > There is fmap from clojure.contrib.generic.functor, which expects a > > function of arity 1, for just the value: > > > (use 'clojure.contrib.generic.functor) > > (require '[clojure.string :as str]) > > > (def my-map {:first "john" :last "smith" :age 25}) > > > (defn my-fn [value] > > (if (string? value) > > (str/upper-case value) > > value)) > > > user=> (fmap my-fn my-map) > > {:first "JOHN", :last "SMITH", :age 25} > > > On Feb 22, 4:23 pm, rob levy wrote: > > > The usual intuitive options for this are reduce, zipmap, or into. You > > can > > > also write a lazily recursive solution. I wonder why there's no function > > in > > > core that lazily re-constructs the map with the results of the function? > > It > > > seems to have been discussed on the list at least once or twice. It > > seems > > > like there would have to be two versions of it, one expecting a function > > > with an arity of one (for just the value) and another expecting an arity > > of > > > two (key and value). > > > > On Mon, Feb 21, 2011 at 10:08 PM, yair wrote: > > > > I'm hoping this is a dumb question and I've missed something obvious. > > > > I have a map with various key-value pairs and I want to transform some > > > > of the values, e.g. > > > > > (def mymap {:first "john" :last "smith" :age 25}) and say I want to > > > > change the strings to be upper case. > > > > Right now all I can think of doing is using reduce and passing in an > > > > empty map and the re-associating each key with the (possibly) > > > > transformed value. Is there something like the map function that > > > > takes two parameters, one a function that receives a pair and returns > > > > a new pair, and the other a map, and returns a map that's > > > > reconstituted from those pairs? > > > > > Thanks > > > > > -- > > > > You received this message because you are subscribed to the Google > > > > Groups "Clojure" group. > > > > To post to this group, send email to clojure@googlegroups.com > > > > Note that posts from new members are moderated - please be patient with > > > > your first post. > > > > To unsubscribe from this group, send email to > > > > clojure+unsubscr...@googlegroups.com > > > > For more options, visit this group at > > > >http://groups.google.com/group/clojure?hl=en > > > -- > > You received this message because you are subscribed to the Google > > Groups "Clojure" group. > > To post to this group, send email to clojure@googlegroups.com > > Note that posts from new members are moderated - please be patient with > > your first post. > > To unsubscribe from this group, send email to > > clojure+unsubscr...@googlegroups.com > > For more options, visit this group at > >http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
Yes, it is guaranteed, and I'm dubious about your claim about serializing. (seq foo) will return the entries in foo in the same order always; but (seq (assoc foo 1 2)) may return the entries in a completely different order. You can treat (keys x) as if it were defined by (map key (seq x)): user=> (let [x (meta #'first)] (= (keys x) (map key x))) true On Feb 22, 4:17 pm, Mike Meyer wrote: > On Tue, 22 Feb 2011 15:36:02 -0800 (PST) > > Daniel Bell wrote: > > I can't think of anything core, but > > > (let [f #(. % toUpperCase)] > > (zipmap (keys skills) (map f (vals skills doesn't seem too bad. > > Does clojure guarantee that keys & vals return things in the proper > order for this to work? Since it doesn't guarantee that serializing > the entries of a map will always get the same order, that seems > unlikely. > > thanks, > -- > Mike Meyer http://www.mired.org/consulting.html > Independent Software developer/SCM consultant, email for more information. > > O< ascii ribbon campaign - stop html mail -www.asciiribbon.org -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
Augh, my eyes! Seriously though, you can save yourself some pain. If you're going to destructure in an anonymous function, just use (fn) instead of the now- actually-longhand #() shorthand form: (fn [[k v]] ...) vs #(let [[k v] %] ...) is clearer and doesn't stop you using another #() nested within or without. Related advice, which I always forget when I'm writing my own code, is that you usually don't want to map an anonymous function; instead, use for: (for [[k v] my-seq] (do-stuff-with k v)) is clearer than (map (fn [[k v]] (do-stuff-with k v)) my-seq) On Feb 22, 3:27 pm, Nurullah Akkaya wrote: > You can use map to get your new sequence of pairs, the turn it into a > hash-map using into, > > (->> {:first "john" :last "smith" :age 25} > (map #(let [[k v] %] > (if (string? v) > [k (.toUpperCase v)] [k v]))) > (into {})) > > Best, > -- > Nurullah Akkayahttp://nakkaya.com > > On Tuesday, February 22, 2011 at 5:08 AM, yair wrote: > > I'm hoping this is a dumb question and I've missed something obvious. > > I have a map with various key-value pairs and I want to transform some > > of the values, e.g. > > > (def mymap {:first "john" :last "smith" :age 25}) and say I want to > > change the strings to be upper case. > > Right now all I can think of doing is using reduce and passing in an > > empty map and the re-associating each key with the (possibly) > > transformed value. Is there something like the map function that > > takes two parameters, one a function that receives a pair and returns > > a new pair, and the other a map, and returns a map that's > > reconstituted from those pairs? > > > Thanks > > > -- > > You received this message because you are subscribed to the Google > > Groups "Clojure" group. > > To post to this group, send email to clojure@googlegroups.com > > Note that posts from new members are moderated - please be patient with > > your first post. > > To unsubscribe from this group, send email to > > clojure+unsubscr...@googlegroups.com > > For more options, visit this group at > >http://groups.google.com/group/clojure?hl=en > > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
On Tue, 22 Feb 2011 15:36:02 -0800 (PST) Daniel Bell wrote: > I can't think of anything core, but > > (let [f #(. % toUpperCase)] > (zipmap (keys skills) (map f (vals skills doesn't seem too bad. Does clojure guarantee that keys & vals return things in the proper order for this to work? Since it doesn't guarantee that serializing the entries of a map will always get the same order, that seems unlikely. thanks, http://www.mired.org/consulting.html Independent Software developer/SCM consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
Yeah, fmap is perfect and definitely the most elegant for the specific problem described by the OP. I had never heard of that one. On Tue, Feb 22, 2011 at 6:56 PM, Benny Tsai wrote: > There is fmap from clojure.contrib.generic.functor, which expects a > function of arity 1, for just the value: > > (use 'clojure.contrib.generic.functor) > (require '[clojure.string :as str]) > > (def my-map {:first "john" :last "smith" :age 25}) > > (defn my-fn [value] > (if (string? value) >(str/upper-case value) >value)) > > user=> (fmap my-fn my-map) > {:first "JOHN", :last "SMITH", :age 25} > > On Feb 22, 4:23 pm, rob levy wrote: > > The usual intuitive options for this are reduce, zipmap, or into. You > can > > also write a lazily recursive solution. I wonder why there's no function > in > > core that lazily re-constructs the map with the results of the function? > It > > seems to have been discussed on the list at least once or twice. It > seems > > like there would have to be two versions of it, one expecting a function > > with an arity of one (for just the value) and another expecting an arity > of > > two (key and value). > > > > > > > > > > > > > > > > On Mon, Feb 21, 2011 at 10:08 PM, yair wrote: > > > I'm hoping this is a dumb question and I've missed something obvious. > > > I have a map with various key-value pairs and I want to transform some > > > of the values, e.g. > > > > > (def mymap {:first "john" :last "smith" :age 25}) and say I want to > > > change the strings to be upper case. > > > Right now all I can think of doing is using reduce and passing in an > > > empty map and the re-associating each key with the (possibly) > > > transformed value. Is there something like the map function that > > > takes two parameters, one a function that receives a pair and returns > > > a new pair, and the other a map, and returns a map that's > > > reconstituted from those pairs? > > > > > Thanks > > > > > -- > > > You received this message because you are subscribed to the Google > > > Groups "Clojure" group. > > > To post to this group, send email to clojure@googlegroups.com > > > Note that posts from new members are moderated - please be patient with > > > your first post. > > > To unsubscribe from this group, send email to > > > clojure+unsubscr...@googlegroups.com > > > For more options, visit this group at > > >http://groups.google.com/group/clojure?hl=en > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
Yeah, after I wrote that, it occurred to me that there are good reasons why Clojure nudges you away from doing lazy operations on maps, although I hadn't thought much about it. I didn't think of walk. That is probably the most elegant out of the approaches I have seen to this common problem. On Tue, Feb 22, 2011 at 6:43 PM, Alan wrote: > On Feb 22, 3:23 pm, rob levy wrote: > > The usual intuitive options for this are reduce, zipmap, or into. You > can > > also write a lazily recursive solution. I wonder why there's no function > in > > core that lazily re-constructs the map with the results of the function? > It > > seems to have been discussed on the list at least once or twice. It > seems > > like there would have to be two versions of it, one expecting a function > > with an arity of one (for just the value) and another expecting an arity > of > > two (key and value). > > Maps aren't lazy. They would be seqs if they were lazy, and not have > fast lookup by key. > > clojure.contrib.generic.functor/fmap updates values, and clojure.walk/ > walk (and maybe post-walk) can do what you're looking for with pairs: > > user=> (walk (fn [[k v]] [v k]) identity {:a 1 :b 2}) > {1 :a, 2 :b} > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
There is fmap from clojure.contrib.generic.functor, which expects a function of arity 1, for just the value: (use 'clojure.contrib.generic.functor) (require '[clojure.string :as str]) (def my-map {:first "john" :last "smith" :age 25}) (defn my-fn [value] (if (string? value) (str/upper-case value) value)) user=> (fmap my-fn my-map) {:first "JOHN", :last "SMITH", :age 25} On Feb 22, 4:23 pm, rob levy wrote: > The usual intuitive options for this are reduce, zipmap, or into. You can > also write a lazily recursive solution. I wonder why there's no function in > core that lazily re-constructs the map with the results of the function? It > seems to have been discussed on the list at least once or twice. It seems > like there would have to be two versions of it, one expecting a function > with an arity of one (for just the value) and another expecting an arity of > two (key and value). > > > > > > > > On Mon, Feb 21, 2011 at 10:08 PM, yair wrote: > > I'm hoping this is a dumb question and I've missed something obvious. > > I have a map with various key-value pairs and I want to transform some > > of the values, e.g. > > > (def mymap {:first "john" :last "smith" :age 25}) and say I want to > > change the strings to be upper case. > > Right now all I can think of doing is using reduce and passing in an > > empty map and the re-associating each key with the (possibly) > > transformed value. Is there something like the map function that > > takes two parameters, one a function that receives a pair and returns > > a new pair, and the other a map, and returns a map that's > > reconstituted from those pairs? > > > Thanks > > > -- > > You received this message because you are subscribed to the Google > > Groups "Clojure" group. > > To post to this group, send email to clojure@googlegroups.com > > Note that posts from new members are moderated - please be patient with > > your first post. > > To unsubscribe from this group, send email to > > clojure+unsubscr...@googlegroups.com > > For more options, visit this group at > >http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
Another idea I had is something like this: (hashmap (flatten (map #(...) oldmap))), since calling map on a map returns a sequence of whatever the function returns, but this isn't the neatest solution either... On Feb 23, 10:23 am, rob levy wrote: > The usual intuitive options for this are reduce, zipmap, or into. You can > also write a lazily recursive solution. I wonder why there's no function in > core that lazily re-constructs the map with the results of the function? It > seems to have been discussed on the list at least once or twice. It seems > like there would have to be two versions of it, one expecting a function > with an arity of one (for just the value) and another expecting an arity of > two (key and value). > > > > > > > > On Mon, Feb 21, 2011 at 10:08 PM, yair wrote: > > I'm hoping this is a dumb question and I've missed something obvious. > > I have a map with various key-value pairs and I want to transform some > > of the values, e.g. > > > (def mymap {:first "john" :last "smith" :age 25}) and say I want to > > change the strings to be upper case. > > Right now all I can think of doing is using reduce and passing in an > > empty map and the re-associating each key with the (possibly) > > transformed value. Is there something like the map function that > > takes two parameters, one a function that receives a pair and returns > > a new pair, and the other a map, and returns a map that's > > reconstituted from those pairs? > > > Thanks > > > -- > > You received this message because you are subscribed to the Google > > Groups "Clojure" group. > > To post to this group, send email to clojure@googlegroups.com > > Note that posts from new members are moderated - please be patient with > > your first post. > > To unsubscribe from this group, send email to > > clojure+unsubscr...@googlegroups.com > > For more options, visit this group at > >http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
On Feb 22, 3:23 pm, rob levy wrote: > The usual intuitive options for this are reduce, zipmap, or into. You can > also write a lazily recursive solution. I wonder why there's no function in > core that lazily re-constructs the map with the results of the function? It > seems to have been discussed on the list at least once or twice. It seems > like there would have to be two versions of it, one expecting a function > with an arity of one (for just the value) and another expecting an arity of > two (key and value). Maps aren't lazy. They would be seqs if they were lazy, and not have fast lookup by key. clojure.contrib.generic.functor/fmap updates values, and clojure.walk/ walk (and maybe post-walk) can do what you're looking for with pairs: user=> (walk (fn [[k v]] [v k]) identity {:a 1 :b 2}) {1 :a, 2 :b} -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
I can't think of anything core, but (let [f #(. % toUpperCase)] (zipmap (keys skills) (map f (vals skills doesn't seem too bad. On Feb 21, 8:08 pm, yair wrote: > I'm hoping this is a dumb question and I've missed something obvious. > I have a map with various key-value pairs and I want to transform some > of the values, e.g. > > (def mymap {:first "john" :last "smith" :age 25}) and say I want to > change the strings to be upper case. > Right now all I can think of doing is using reduce and passing in an > empty map and the re-associating each key with the (possibly) > transformed value. Is there something like the map function that > takes two parameters, one a function that receives a pair and returns > a new pair, and the other a map, and returns a map that's > reconstituted from those pairs? > > Thanks -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
You can use map to get your new sequence of pairs, the turn it into a hash-map using into, (->> {:first "john" :last "smith" :age 25} (map #(let [[k v] %] (if (string? v) [k (.toUpperCase v)] [k v]))) (into {})) Best, -- Nurullah Akkaya http://nakkaya.com On Tuesday, February 22, 2011 at 5:08 AM, yair wrote: > I'm hoping this is a dumb question and I've missed something obvious. > I have a map with various key-value pairs and I want to transform some > of the values, e.g. > > (def mymap {:first "john" :last "smith" :age 25}) and say I want to > change the strings to be upper case. > Right now all I can think of doing is using reduce and passing in an > empty map and the re-associating each key with the (possibly) > transformed value. Is there something like the map function that > takes two parameters, one a function that receives a pair and returns > a new pair, and the other a map, and returns a map that's > reconstituted from those pairs? > > Thanks > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with your > first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
The usual intuitive options for this are reduce, zipmap, or into. You can also write a lazily recursive solution. I wonder why there's no function in core that lazily re-constructs the map with the results of the function? It seems to have been discussed on the list at least once or twice. It seems like there would have to be two versions of it, one expecting a function with an arity of one (for just the value) and another expecting an arity of two (key and value). On Mon, Feb 21, 2011 at 10:08 PM, yair wrote: > I'm hoping this is a dumb question and I've missed something obvious. > I have a map with various key-value pairs and I want to transform some > of the values, e.g. > > (def mymap {:first "john" :last "smith" :age 25}) and say I want to > change the strings to be upper case. > Right now all I can think of doing is using reduce and passing in an > empty map and the re-associating each key with the (possibly) > transformed value. Is there something like the map function that > takes two parameters, one a function that receives a pair and returns > a new pair, and the other a map, and returns a map that's > reconstituted from those pairs? > > Thanks > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transforming map entries
Hi, I thought update-in could help but it looks as complicated as your solution: (use 'clojure.contrib.string) (loop [m mymap, ks (keys m)] (let [new-m (update-in m [(first ks)] #(if (string? %) (upper-case %) %)) more (rest ks)] (if-not (empty? more) (recur new-m more) new-m))) I'm a total newbie so I may also miss an obvious and more simple solution. 2011/2/21 yair > I'm hoping this is a dumb question and I've missed something obvious. > I have a map with various key-value pairs and I want to transform some > of the values, e.g. > > (def mymap {:first "john" :last "smith" :age 25}) and say I want to > change the strings to be upper case. > Right now all I can think of doing is using reduce and passing in an > empty map and the re-associating each key with the (possibly) > transformed value. Is there something like the map function that > takes two parameters, one a function that receives a pair and returns > a new pair, and the other a map, and returns a map that's > reconstituted from those pairs? > > Thanks > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en -- Damien Lepage http://damienlepage.com -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Transforming map entries
I'm hoping this is a dumb question and I've missed something obvious. I have a map with various key-value pairs and I want to transform some of the values, e.g. (def mymap {:first "john" :last "smith" :age 25}) and say I want to change the strings to be upper case. Right now all I can think of doing is using reduce and passing in an empty map and the re-associating each key with the (possibly) transformed value. Is there something like the map function that takes two parameters, one a function that receives a pair and returns a new pair, and the other a map, and returns a map that's reconstituted from those pairs? Thanks -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en