Is there any good reason why Hash#map does not give back a Hash (Ruby
1.8 but same in 1.9 as far as I know)? I often find myself writing
these kind of things:
newhash = oldhash.inject({}) { |h,(k,v)| h[k] = some_operation(v); h }
but that doesn't look pretty at all in my opinion. I want to just
write like this:
newhash = oldhash.map { |k,v| some_operation(v) }
I finally got around to change this behaviour for my own code, but are
all Ruby users supposed to invent this wheel on their own? Wouldn't it
be better if Hash#map behaved like this? Or is there something I am
missing?
class Hash
def hashmap
self.inject({}) do |newhash, (k,v)|
newhash[k] = yield(k, v)
newhash
end
end
end
Regards,
Fredrik
on 2009-04-29 08:04
on 2009-04-29 08:14
On Wed, Apr 29, 2009 at 8:00 AM, Fredrik <fredjoha@gmail.com> wrote: > > end > end > end > > > Regards, > Fredrik > Becuase #map comes from form Enumerable (and is an alias for collect) enum.collect {| obj | block } => array enum.map {| obj | block } => array Returns a new array with the results of running block once for every element in enum. (1..4).collect {|i| i*i } #=> [1, 4, 9, 16] (1..4).collect { "cat" } #=> ["cat", "cat", "cat", "cat"] Andrew Timberlake http://ramblingsonrails.com http://www.linkedin.com/in/andrewtimberlake "I have never let my schooling interfere with my education" - Mark Twain
on 2009-04-29 08:21
irb(main):041:0> o={"a",1,"b",2}
=> {"a"=>1, "b"=>2}
irb(main):042:0> o.merge(o){|k,ov|ov*2}
=> {"a"=>2, "b"=>4}
on 2009-04-29 08:30
class Hash
def new_map
result = self.map do |k,v|
r = yield v
[k,r]
end
Hash[*result.flatten]
end
end
a = {}
a[2] = 4
a[3] = 6
b=a.new_map do |v|
v+2
end
puts b.class
puts b.inspect
yields:
Hash
{2=>6, 3=>8}
Does this help?
Jayanth
on 2009-04-29 08:35
Fredrik wrote: > Is there any good reason why Hash#map does not give back a Hash (Ruby > 1.8 but same in 1.9 as far as I know)? I often find myself writing > these kind of things: > > newhash = oldhash.inject({}) { |h,(k,v)| h[k] = some_operation(v); h } > > but that doesn't look pretty at all in my opinion. I want to just > write like this: > > newhash = oldhash.map { |k,v| some_operation(v) } > class Hash def hashbackmap result = {} self.each do |key, val| result[key] = yield val end result end end h = { "red" => 10, "blue" => 20, "green" => 30 } p h.hashbackmap {|x| x*2} --output:-- {"green"=>60, "blue"=>40, "red"=>20} I HAVE A PATENT!! My licensing fees are cheap: $10 mth.
on 2009-04-29 14:40
On Apr 29, 2009, at 1:00 AM, Fredrik wrote: > Is there any good reason why Hash#map does not give back a Hash (Ruby > 1.8 but same in 1.9 as far as I know)? It wouldn't make sense for Hash#map to return a Hash since you are not required to transform it into key-value pairs: >> {1 => "one", 2 => "two"}.map { |k, v| "#{k} is #{v}" } => ["1 is one", "2 is two"] > I often find myself writing > these kind of things: > > newhash = oldhash.inject({}) { |h,(k,v)| h[k] = some_operation(v); h } 1.9 adds each_with_object() for this very usage. You don't want the return value of the block to carry forward, but instead the object you started with. That's what each_with_object() does. So your code becomes the following in Ruby 1.9: newhash = oldhash.each_with_object({}) { |(k, v), h| h[k] = some_operation(v) } Hope that helps. James Edward Gray II
on 2009-04-30 01:10
> > Becuase #map comes from form Enumerable (and is an alias for collect) > Well ok, that is a reason but it's not a good motivation why it HAS to be like that. What use does one really have of getting an Array (with elements in an undefined order) from a Hash#map ?
on 2009-04-30 01:21
> irb(main):041:0> o={"a",1,"b",2} > => {"a"=>1, "b"=>2} > irb(main):042:0> o.merge(o){|k,ov|ov*2} > => {"a"=>2, "b"=>4} > Thanks! That's the piece missing from my Ruby skills! :) Though o.merge (o) doesn't look as pedagogically clear as o.map, it'll have to do.
on 2009-04-30 05:28
On 29 Apr, 21:39, James Gray <ja...@grayproductions.net> wrote: > > newhash = oldhash.each_with_object({}) { |(k, v), h| > h[k] = some_operation(v) > > } > > Hope that helps. > > James Edward Gray II Thanks! It's not a very big improvement over inject though. I don't see the use of Hash#map -> Array so if it was up to me, Hash#map would give a Hash. If one really wants an Array it seems more reasonable to use something like hash.to_a{|k,v| "#{k} is #{v}" } Maybe it's just me, but when I read "map" I am thinking "map this block to each element and give back the same structure" (i.e. Array#map gives an Array and Hash#map gives a Hash). (I know map is just an alias for collect, but I never understood why "collect" is a good name for this method.)
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.