Given a map with keyword keys, I need a map with uppercase string keys
- and vice versa.
{ :stuff 42 :like 13 :this 7 } <=> { "STUFF" 42 "LIKE" 13 "THIS" 7 }
I've come up with various functions to do this but so far they all
feel a bit clunky.
Any suggestions for the simplest, most idiomatic solution?
Here's one pair of functions I came up with...
(defn- to-struct [r] (apply hash-map (flatten (map (fn [[k v]]
[(s/upper-case (name k)) v]) r))))
(defn- to-rec [m] (apply hash-map (flatten (map (fn [[k v]] [(keyword
(s/lower-case k)) v]) m))))
s is clojure.string:
(:use [clojure.string :as s :only (lower-case upper-case)])
I came up with some using assoc and/or dissoc as well... didn't like
those much either :)
--
Sean A Corfield -- (904) 302-SEAN
Railo Technologies, Inc. -- http://getrailo.com/
An Architect's View -- http://corfield.org/
"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood
What about this -
(into {} (for [[k v] { :stuff 42 :like 13 :this 7 }]
[(.toUpperCase (name k)) v]))
Regards,
BG
--
Baishampayan Ghose
b.ghose at gmail.com
>> I have a need to convert maps in the following ways:
>>
>> Given a map with keyword keys, I need a map with uppercase string keys
>> - and vice versa.
>>
>> { :stuff 42 :like 13 :this 7 } <=> { "STUFF" 42 "LIKE" 13 "THIS" 7 }
>
> What about this -
>
> (into {} (for [[k v] { :stuff 42 :like 13 :this 7 }]
> [(.toUpperCase (name k)) v]))
>
One small suggestion based on something Christophe Grand once pointed out:
(defn string-keys [m]
(into (empty m) (for [[k v] m] [(.toUpperCase (name k)) v])))
(defn keyword-keys [m]
(into (empty m) (for [[k v] m] [(keyword (.toLowerCase k)) v])))
This will preserve the type of the map.
(string-keys { :stuff 42 :like 13 :this 7 } ) => {"THIS" 7, "LIKE" 13, "STUFF" 42}
(keyword-keys (string-keys { :stuff 42 :like 13 :this 7 } )) => {:stuff 42, :like 13, :this 7}
Have all good days,
David Sletten
(defn- to-struct [r] (into {} (for [[k v] r] [(.toUpperCase (name k)) v]))
That is certainly nicer than most of my attempts, thank you!
Any reason for .toUpperCase instead of clojure.string/upper-case?
Thanx also to David for the (empty m) tip (but I'm only working with
hash maps at the moments).
clojure.contrib.string/upper-case is a trivial wrapper over
.toUpperCase. In my humble opinion it's perfectly OK to use such
static Java methods directly instead of writing trivial wrappers
around them.
This also helps in avoiding the contrib dependency.
Good point. Thanx BG.
Except that if you use .toUpperCase, you have to remember to type hint
the input. Any time you call a Java method without type hinting, you
take a significant performance hit. The wrapper function takes care
of that for you.
That's very similar to one of my attempts and... I don't know... I
just don't like it as much. Splitting the map into two streams and
zipping them back together just doesn't feel as 'nice' and making one
pass over the key/value pairs of the map...
Interesting choice of comp - I think I went with #(s/upper-case (name
%)) - I guess comp is more idiomatic, functionally?
Good to know, thanx Mark.
Keep 'em coming folks, this is exactly what I was hoping for when I
posted the question.
> On Thu, Sep 30, 2010 at 12:30 AM, Mark Engelberg
> <mark.en...@gmail.com> wrote:
>> Except that if you use .toUpperCase, you have to remember to type hint
>> the input. Any time you call a Java method without type hinting, you
>> take a significant performance hit. The wrapper function takes care
>> of that for you.
>
> Good to know, thanx Mark.
>
> Keep 'em coming folks, this is exactly what I was hoping for when I
> posted the question.
>
Huh?! How many solutions do you want? You're starting to annoy me Sean.
Hmm, I guess you must really be alive. :)
Sorry dude. I think it's really insightful to see lots of different
solutions to small point problems like this when you're learning a
language - particularly when the issue of idiom is being discussed.
I've certainly found this thread educational and I hope I'm not
annoying too many people :)
Things I'm finding particularly helpful:
* into / for
* comp vs #() vs ->
* split a map and zip it vs a single pass with a more complex function
The into / for thing was great because it's something that seems very
Clojurish that I wouldn't have thought of without input.
I'm very excited about Clojure. I think it's going to be core to my
team's work over the next couple of years. I haven't been able to do
serious functional programming for about three decades but Clojure
really provides that option. We're already using Scala for certain
performance-critical pieces of our system but it's not a language that
I can present to most of my web developers - they're used to dynamic
scripting languages, no type system, no compile/deploy/run cycle.
--
Sean A Corfield -- (904) 302-SEAN
Railo Technologies, Inc. -- http://getrailo.com/
An Architect's View -- http://corfield.org/
"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood
> On Thu, Sep 30, 2010 at 12:52 AM, David Sletten <da...@bosatsu.net> wrote:
>> Huh?! How many solutions do you want? You're starting to annoy me Sean.
>
> Sorry dude. I think it's really insightful to see lots of different
> solutions to small point problems like this when you're learning a
> language - particularly when the issue of idiom is being discussed.
> I've certainly found this thread educational and I hope I'm not
> annoying too many people :)
>
Sean, Sean...I was just making fun of your signature. :)
Keep up the questions!
Phew! Just checking...
(I'm on some lists where the response to similar questions has been
"You want me to do your homework?"...)
--
Sean A Corfield -- (904) 302-SEAN
Railo Technologies, Inc. -- http://getrailo.com/
An Architect's View -- http://corfield.org/
"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood
The Clojure community is certainly not one of those.