the_
the_

Reputation: 1173

Capitalize each key in hash

I have a long hash that looks like this (this is only part of it):

countries =
  [
    ['AFGHANISTAN','AF'],
    ['ÅLAND ISLANDS','AX'],
    ['ALBANIA','AL'],
    ['ALGERIA','DZ'],
    ['AMERICAN SAMOA','AS']
  ]

I want to capitalize the keys of each value. So AFGHANISTAN would go to Afghanistan. Then I want to get the same hash back.

I've tried using this:

countries.each do |key, value|
  puts key.capitalize
end

but it only gives me the keys back. I want to put the capitalized keys back into the hash. How can I do this?

Upvotes: 0

Views: 3585

Answers (3)

vgoff
vgoff

Reputation: 11313

Your "Hash" isn't a Hash, but an Array.

countries.each do |name, abbreviation|
  temp = name.dup 
  name.clear
  name << temp.split(' ').map(&:capitalize!).join(' ')
end

This will change each of the names to a capitalized name in place.

[
 ["Afghanistan", "AF"],
 ["Åland Islands", "AX"],
 ["Albania", "AL"],
 ["Algeria", "DZ"],
 ["American Samoa", "AS"]
]

This addresses more than one word as well, and because you mentioned wanting to keep the same "hash" this keeps the same Array, the object_id (of the Array, of course, but also of each String) doesn't change, it changes it in place.

There is even no problem for nations such as the country of Éclair, as @muistooshort mentions. However, if you have an acute character (for example) that is capitalized in the middle of the word, capitalize does not handle such things, and there is yet more work to be done.

Upvotes: 2

falsetru
falsetru

Reputation: 369134

The code does not modify the hash. It just print capitalized keys.

You should remove old entries and add new entries. Or create new hash as follow:

countries = Hash[[
  ['AFGHANISTAN','AF'],
  ['ÅLAND ISLANDS','AX'],
  ['ALBANIA','AL'],
  ['ALGERIA','DZ'],
  ['AMERICAN SAMOA','AS']
]]
countries = Hash[countries.map {|country, abbr| [country.capitalize, abbr] }]
# => {
#   "Afghanistan"=>"AF",
#   "Åland islands"=>"AX",
#   "Albania"=>"AL",
#   "Algeria"=>"DZ",
#   "American samoa"=>"AS"
# }

Upvotes: 3

probablykabari
probablykabari

Reputation: 1389

#each doesn't modify the enumerable, it just iterates over it. You want to use #inject (http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-inject)

Like:

countries.inject({}){|caps_hash,og_hash| caps_hash.merge(og_hash[0].capitalize => og_hash[1] ) }

Upvotes: 0

Related Questions