Updating all values in a Hash

Does anyone know a good way to update all values in a hash.

E.g. If I have a big hash with each element containing a string as a
value, how can I make each string lower-case?

Paul Dugdale wrote:

If I have a big hash with each element containing a string as a
value, how can I make each string lower-case?

hash.each {|k,v| v.downcase!}
Or if you can’t use destructive methods:
hash.each {|k,v| hash[k] = v.downcase}

HTH,
Sebastian

I found this way

h = Hash.new

def h.
super.downcase
end

h[“ciao”] = “CIOOOO”

puts h[“ciao”]

cioooo

On May 13, 2008, at 8:20 AM, Paul Dugdale wrote:

Does anyone know a good way to update all values in a hash.

E.g. If I have a big hash with each element containing a string as a
value, how can I make each string lower-case?

h = {1 => ‘ONE’, 2 => ‘TWO’}
h.each {|k,v| v.downcase!}

This assumes that all your values really are strings. You’ll get some
errors if any of the values do not have a downcase! methd.

Blessings,
TwP

Hi –

On Tue, 13 May 2008, Sandro P. wrote:

I found this way

cioooo

That’s very resourceful (I’m fully in favor of extending individual
objects), but I’m afraid it doesn’t really do what Paul wants. All it
does is downcase what you see when you do h[val]. But the actual value
doesn’t change:

h = {}
=> {}

def h.; super.downcase; end
=> nil

h[“a”] = “ABC”
=> “ABC”

h[“a”] # This gives you downcased string.
=> “abc”

h.fetch(“a”) # But this doesn’t.
=> “ABC”

h.values # Neither does this.
=> [“ABC”]

I think also that Paul is dealing with a hash that already has some
values, so the iterative solutions might be better.

David

Sorry! I was trying to keep my post simple, but ended up doing a really
bad job of explaining what I was trying to achieve…

I come from a C programming background, so I’m always thinking in terms
of pass-by-value and pass-by-reference.

What I was trying to find out is - is there any way of passing a
reference to the value to the ‘each’ block, rather than a copy of the
value.

I.e. some easy way of doing this:
hash.each { |k,v| v = my_value }

Without having to refer to the hash again in the block like this:
hash.each { |k,v| hash[k] = my_value }

On 13.05.2008 17:46, Paul Dugdale wrote:

Sorry! I was trying to keep my post simple, but ended up doing a really
bad job of explaining what I was trying to achieve…

I come from a C programming background, so I’m always thinking in terms
of pass-by-value and pass-by-reference.

What I was trying to find out is - is there any way of passing a
reference to the value to the ‘each’ block, rather than a copy of the
value.

A reference is indeed passed to the block. There is no copying of
values going on. You can see it because v.downcase! works; this does
change the object referenced by the Hash.

I.e. some easy way of doing this:
hash.each { |k,v| v = my_value }

Without having to refer to the hash again in the block like this:
hash.each { |k,v| hash[k] = my_value }

I’m afraid, you’ll have to use that idiom. The only alternative is to
change your scenario so that it will modify an object, e.g. create an
intermediary:

irb(main):001:0> Holder = Struct.new :val
=> Holder
irb(main):002:0> h={1=>Holder.new(123)}
=> {1=>#}
irb(main):003:0> h.each {|k,v| v.val += 10}
=> {1=>#}
irb(main):004:0>

I doubt though that this is more efficient that using any of

h.keys.each {|k| h[k] += 10}
h.each {|k,v| h[k] = v + 10}

What is the greater context of your issue, i.e. what are you trying to
achieve?

Kind regards

robert

On Tue, May 13, 2008 at 12:04 PM, Sebastian H.
[email protected] wrote:

Paul Dugdale wrote:

What I was trying to find out is - is there any way of passing a
reference to the value to the ‘each’ block, rather than a copy of the
value.

Without having to refer to the hash again in the block like this:
hash.each { |k,v| hash[k] = my_value }

If your v object is immutable, you’ll have to do the above, I’m afraid.

Even if it isn’t not doing so can be problematic:

a = “Fred”
h = {:flintstone => a}
a # => “Fred”
h # => {:flintstone=>“Fred”}
h.each {|k,v| v.downcase!}
h # => {:flintstone=>“fred”}

Expected, but…

a # => “fred”

Expected!!!

Understanding how object reference differs from pointer reference and
value semantics is crucial to starting to understand a pure object
language like Ruby.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Hi –

On Wed, 14 May 2008, Sebastian H. wrote:

Paul Dugdale wrote:

What I was trying to find out is - is there any way of passing a
reference to the value to the ‘each’ block, rather than a copy of the
value.

You always pass by reference, but you pass a reference to the object (a
pointer if you will) not a reference to the variable. You can’t have variable
references in ruby.

I’d put it differently, and I know this sounds convoluted but I think
in the end it turns out to be more apt: You’re passing by value, but
the value you’re passing is a reference to an object.

“Passing by reference” makes it sound (to me) like when you do this:

s = “hi”
my_method(s)

s somehow gets wrapped in a reference on its way to my_method, whereas
it’s actually really just being handed off. The value assigned to the
corresponding parameter in my_method is the same as the value of s:
namely, a reference to that string.

There’s probably some aspect of using literal constructors as method
arguments that needs to be factored in there somewhere…

David

Paul Dugdale wrote:

What I was trying to find out is - is there any way of passing a
reference to the value to the ‘each’ block, rather than a copy of the
value.

You always pass by reference, but you pass a reference to the object (a
pointer if you will) not a reference to the variable. You can’t have
variable
references in ruby.

I.e. some easy way of doing this:
hash.each { |k,v| v = my_value }

v.replace my_value
If v has a replace method

Without having to refer to the hash again in the block like this:
hash.each { |k,v| hash[k] = my_value }

If your v object is immutable, you’ll have to do the above, I’m afraid.

HTH,
Sebastian