[Ruby] How to use hashes

4 minute read

I used to use arrays a lot, but
When I was solving a problem, I couldn’t solve it with an array alone.
I was able to solve it with a hash.
A note about that learning.

Premise

Create a book purchase cost ranking for Mr. A, Mr. B, and Mr. C.
There are three engineers named Mr. A, Mr. B, and Mr. C.
Book purchase costs of 1000 yen, 3000 yen, and 2000 yen, respectively.
In this case, Mr. B is in 1st place, Mr. C is in 2nd place, and Mr. A is in 3rd place.

Given the name of each engineer and book purchase information,
Create a book purchase cost ranking from this information.

input

3-> Number of engineers (number_of_engineers)
A B C-> Engineer’s name (name_of_engineers)
4-> Number of books purchased by engineers (number_of_books)
A 1000-> The name of the engineer who purchased the book and the price of the book (name, price)
B 1000
B 2000
C 2000

output

B
C
A

How to solve

number_of_engineers = gets.to_i 
name_of_engineers = gets.to_s.split(" ") 
number_of_books = gets.to_i 
name_n_price = {}
name_of_engineers.each{|name| name_n_price[name] = 0}  #Commentary 1
number_of_books.times do
  name, price = gets.to_s.split(" ")
  name_n_price.each_key{ |i| name_n_price[i] += price.to_i if i == name}  #Commentary 2
end
puts name_n_price.sort_by{ |name, price| -price}.to_h.keys  #Commentary 3

Commentary

Commentary 1

An empty hash is generated in advance with “name_n_price”.
The name_of_engineers are currently as follows:

name_of_engineers = ["A", "B", "C"]

Get the elements (A, B, C) of this array with the each method and add them as keys in name_n_price.
Also, at this time, since name_n_price [name] = 0, each key has a value of 0.
After this, “A 1000” etc. will be input, so the initial value is set as described above.
By the above operation, “name_n_price” becomes as follows.

name_n_price = {"A"=> 0, "B"=> 0, "C"=> 0}

Commentary 2

At number_of_books.times do ~ end, enter “A 1000” etc. a total of 4 times.
(This time number_of_books = 4)
Generate the following array with name, price = gets.to_s.split (“”).

name, price = ["A", "1000"]

Next, add a value to each key in the hash of name_n_price.
Therefore, each element in name_n_price is acquired by each method.
This time, we will get only the key.
The reason is if you understand that you are adding values to the hash key
I will review it.

irb(main):011:0> h = {} 
=> {}
irb(main):012:0> h[:name] = "suzuki"
=> "suzuki"
irb(main):013:0> p h
{:name=>"suzuki"}
=> {:name=>"suzuki"}

In short, if you have a key (“name” in this case), you can add it by specifying a value (“suzuki” in this case).

Therefore, use “name_n_price.each_key {}”.
There is also each_value that retrieves only the value.

Then, for name_n_price = {“A” => 0, “B” => 0, “C” => 0},
I want to add a value when it corresponds to Mr. A, so I will perform a conditional branch in if minutes.
It is as follows.

if i == name

Here, “i” is A, B, C.
( each_I got the key with key{ |i| ~ }Because it is

Add the last entered price.

name_n_price[i] += price.to_i

If you disassemble the above and write it,

name_n_price[i] = name_n_price[i] + price.to_i

If you write it as an assigned value

name_n_price[A] = 0 + 1000

So

name_n_price = {"A"=> 0, "B"=> 0, "C"=> 0}

But

name_n_price = {"A"=> 1000, "B"=> 0, "C"=> 0}

Will be.

Repeating this three more times will result in

name_n_price = {"A"=> 1000, "B"=> 3000, "C"=> 2000}

Will be.

Commentary 3

Finally, for name_n_price, the key (name) is output in order from the person with the largest amount.

We want to sort the amounts in the hash in descending order, so we use sort_by.
There is also sort, but this is a sort by key, so it cannot be used this time.

By the way, it looks like this when used.

irb(main):017:0> h = {"z" => 1, "f" => 3, "a" => 5}
=> {"z"=>1, "f"=>3, "a"=>5}
irb(main):018:0> h.sort
=> [["a", 5], ["f", 3], ["z", 1]]

The keys are sorted alphabetically.

You can sort the values in descending order by doing the following.

name_n_price.sort_by{ |name, price| -price}
irb(main):019:0> name_n_price = {"A"=> 1000, "B"=> 3000, "C"=> 2000}
=> {"A"=>1000, "B"=>3000, "C"=>2000}
irb(main):020:0> name_n_price.sort_by{ |name, price| -price}
=> [["B", 3000], ["C", 2000], ["A", 1000]]

Now you can sort, but the elements are stored in the array from the hash.
This happens when you run sort_by or sort.
I don’t know why.

Under this condition, I want to get only the key, so
Get the key back in the array into a hash.

To convert the array to a hash, use the to_h method.

name_n_price.sort_by{ |name, price| -price}.to_h
=> {"B"=>3000, "C"=>2000, "A"=>1000}

Also, I want only the keys, so I use the keys method.

name_n_price.sort_by{ |name, price| -price}.to_h.keys
=> ["B", "C", "A"]

Line breaks will occur in the puts method, so if you output the above with puts,
The answer is as expected.

that’s all.

Tags:

Updated: