# Iterating methods on multiple parameters

I’m thinking there must be a great Ruby-way to do the same thing to many
different variables. Here is a boiled down version of what I have:

``````    @yn = Unit.new("#{@yn} feet")
@yc = Unit.new("#{yc} feet")
@v = Unit.new("#{@v} fps")
@twmax = Unit.new("#{@twmax} lbs/ft^2")
@tc = Unit.new("#{@tc} lbs/ft^2")
@twc = Unit.new("#{@twc} lbs/ft^2")
``````

My first thought is to create a hash of variables like this:

``````    results = {'yn' => "#{@yn} feet", 'yc' => "#{yc} feet", 'v' =>
``````

“#{@v} fps”, ‘twmax’ => “#{twmax} lbs/ft^2”, ‘tc’ => “#{tc} lbs/ft^2”,
‘twc’ => “#{twc} lbs/ft^2”}

then use a block something like this?

``````    results.each_value {|item| Unit.new(item)}
``````

…but that doesn’t seem to work. Any ideas to make this better?

Thank you!

Jason L. wrote:

I’m thinking there must be a great Ruby-way to do the same thing to many
different variables. Here is a boiled down version of what I have:

``````    @yn = Unit.new("#{@yn} feet")
@yc = Unit.new("#{yc} feet")
@v = Unit.new("#{@v} fps")
@twmax = Unit.new("#{@twmax} lbs/ft^2")
@tc = Unit.new("#{@tc} lbs/ft^2")
@twc = Unit.new("#{@twc} lbs/ft^2")
``````

My first thought is to create a hash of variables like this:

``````    results = {'yn' => "#{@yn} feet", 'yc' => "#{yc} feet", 'v' =>
``````

“#{@v} fps”, ‘twmax’ => “#{twmax} lbs/ft^2”, ‘tc’ => “#{tc} lbs/ft^2”,
‘twc’ => “#{twc} lbs/ft^2”}

then use a block something like this?

``````    results.each_value {|item| Unit.new(item)}
``````

…but that doesn’t seem to work. Any ideas to make this better?

Thank you!

The most hardcore way:

h={:yn=>“feet”,:yc=>“feet”,…}
h.each_pair
{ |v,u|
iv=:"@#{v}"
instance_variable_set(iv,Unit::new("#{instance_variable_get(iv)} #{u}"))
}

Or there are some variations using eval, but I think using eval is less
elegant.

TPR.

Thank you.

But I think my problem is simpler than that. I didn’t explain well
enough.

I’m finding that with either each_pair or each_value, I can’t get what I
need.

here is a simple case:

h = {‘x’=>2, ‘y’=>5}

I want to change the values of the hash and assign those to new hash:

i = h.each_value {|v| v * 2}

I wanted i => {‘x’=>4, ‘y’=>10} but it remains i => {‘x’=>2, ‘y’=>5}

Is there some form of a ‘collect’ method for hashes - similar to array?
There must be some other easy answer.

thank you!

I just saw a similar issue (#163350 of this forum).

seems like this might work to change values of a hash:

hash = {‘x’=>2, ‘y’=5}
hash_new = hash.inject({}) do |h, (k,v)|
h[v * 2] = k
h
end

although this returns {10=>“y”, 4=>“x”}

something seems amiss…

what do you think?

Jason L. wrote:

I just saw a similar issue (#163350 of this forum).

seems like this might work to change values of a hash:

hash = {‘x’=>2, ‘y’=5}
hash_new = hash.inject({}) do |h, (k,v)|
h[v * 2] = k
h
end

although this returns {10=>“y”, 4=>“x”}

something seems amiss…

hash = {‘x’=>2, ‘y’=>5}
hash_new = hash.inject({}) do |h, (k,v)|
h[k] = v * 2
h
end

Thanks everyone!

Is there a reason the hsh.inject method is not included in the Ruby
documentation?

On Sat, Sep 20, 2008 at 6:59 PM, Jason L.
[email protected] wrote:

although this returns {10=>“y”, 4=>“x”}

h = Hash[‘x’, 2, ‘y’, 5]
h.each_key {|k| h[k] *= 2}

Todd

really hard to learn!

I was looking in http://www.ruby-doc.org/core/

and just went to Class Hash and didn’t see that method. I didn’t think
of Enumerable. I originally thought the collect method would work
similar to arrays and noticed in Google searching someone said Hashes
don’t have collect. So then I just assumed Hashes must also be missing
inject as well.

On Sep 21, 2008, at 3:57 PM, Jason L. wrote:

Thanks everyone!

Is there a reason the hsh.inject method is not included in the Ruby
documentation?

Sure it is. In my Programming Ruby, 2 ed., on page 492 it say that
Hash mixes in the Enumerable module and lists inject as one of the
methods. Enumerable#inject itself is documented on page 456.

Depending on where/how you’re looking, it is!

\$ ri Hash#inject

## \$ fri Hash#inject ------------------------------------------------------ Enumerable#inject enum.inject(initial) {| memo, obj | block } => obj enum.inject {| memo, obj | block } => obj

``````  Combines the elements of enum by applying the block to an
accumulator value (memo) and each element in turn. At each step,
memo is set to the value returned by the block. The first form
lets you supply an initial value for memo. The second form uses
the first element of the collection as a the initial value (and
skips that element while iterating).

# Sum some numbers
(5..10).inject {|sum, n| sum + n }              #=> 45
# Multiply some numbers
(5..10).inject(1) {|product, n| product * n }   #=> 151200

# find the longest word
longest = %w{ cat sheep bear }.inject do |memo,word|
memo.length > word.length ? memo : word
end
longest                                         #=> "sheep"

# find the length of the longest word
longest = %w{ cat sheep bear }.inject(0) do |memo,word|
memo >= word.length ? memo : word.length
end
longest                                         #=> 5
``````

What leads you to think that it isn’t documented?

-Rob