Sammy AbuKmeil
Sammy AbuKmeil

Reputation: 103

How do the parameters in ruby '.each do' for-loops work?

What's confusing me in the code below is how the parameters state and abbrev match up with the keys and and the values of the hash? Or in other words, how is state matched up with 'oregon' and abbrev with 'OR' (if the parameters matched words in the hash, then I could understand that)

Are they matched up correctly because the first parameter is paired with the first value in the code block?

states = {
  'Oregon' => 'OR',
  'Florida' => 'FL',
  'California' => 'CA',
  'New York' => 'NY',
  'Michigan' => 'MI'
}

states.each do |state, abbrev|
  puts "#{state} is abbreviated #{abbrev}"
end

The output of this code:

Oregon is abbreviated OR
Florida is abbreviated FL
California is abbreviated CA
New York is abbreviated NY
Michigan is abbreviated MI

Sorry for not being able to put my question across clearly, still new to this :S

Thanks!

Upvotes: 3

Views: 7307

Answers (3)

iced
iced

Reputation: 1582

class Powers
  def initialize(x)
    @x = x
  end

  def each(&block)
    yield 1, @x
    yield 2, @x * @x
    yield 3, @x * @x * @x
  end
end

p = Powers.new(3)
p.each do |n, r|
  puts "#{n} -> #{r}"
end

Here is simple demo for you. No explanation needed I think :)

Upvotes: -3

jdussault
jdussault

Reputation: 427

each is going through each pair in the hash and then using general terms to describe the pair so that you can write code that will work for everything in your hash.

It might be easier to see what is going on if you look at how it operates on an array.

[1, 2, 3, 4, 5].each do |num|
  puts "Number is #{num}"
end

There are five elements in the above array. I chose to call them "num" since they are all numbers, but I could have called each specific element "item" or "element" or "poodle" or "potato" or anything you like. The name inside of the | | bars is really just how you are referring to an individual item inside the array or hash in the block.

Now let's do the same thing with a hash.

hash = {
  1 => "one",
  2 => "two",
  3 => "three"
}
hash.each do |item|
  puts "item: #{item}"
end

This will output:

item: [1, "one"]
item: [2, "two"]
item: [3, "three"]

Ideally, we want to be able to work with both the key and the value in a hash when we're iterating through, so you would want to do something more along these lines:

hash.each do |key, value|
  puts "key: #{key}, value: #{value}"
end

Outputs:

key: 1, value: one
key: 2, value: two
key: 3, value: three

The each method on hashes is essentially each_pair (http://ruby-doc.org/core-2.1.0/Hash.html#method-i-each_pair). That way, Ruby expects that if you give it two variable names, you must be operating on the key and value of each element in the hash. There are some other helpful methods like each_key and each_value that you may find interesting as well.

I don't know if that answered your question at all. Let me know if I can elaborate!

Upvotes: 4

tadman
tadman

Reputation: 211740

The each method iterates over key/value pairs when you're operating on a Hash structure. If you define your block to accept two values, this is how they'll break out.

In this particular case, the key is state and the value is abbrev, so it all works out.

Upvotes: 0

Related Questions