Ruby - remove underscores and capitalize
Asked Answered
S

5

17

Okay so I'm trying to remove the underscores, as seen in some of the holidays (for example,fourth_of_july). Then I want to capitalize each of the words.

Expected result: fourth_of_july > Fourth Of July

so this is my code:

holiday_dec = {

:winter => {
   :christmas => ["Lights", "Wreath"],
   :new_years => ["Party Hats"]
 },
 :summer => {
   :fourth_of_july => ["Fireworks", "BBQ"]
 },
 :fall => {
   :thanksgiving => ["Turkey"]
 },
 :spring => {
   :memorial_day => ["BBQ"]
 }

}

def all_supplies_in_holidays(holiday_hash)

  holiday_hash.each do |seasons, holidays|

    holidays.each do |holidays, supplies|
      puts "#{seasons.to_s.capitalize}:"
      puts "  #{holidays.to_s.tr("_"," ").capitalize}: #{supplies.join(", ")}"
    end

  end

end

all_supplies_in_holidays(holiday_dec)
Shela answered 17/11, 2016 at 0:47 Comment(1)
Why the rush to select an answer?Armstrong
S
11

You can use this one liner

str.split('_').map(&:capitalize).join(' ')

This takes a string str and splits it where the underscores are, then capitalizes each word then joins the words together with a space. Example

"fourth_of_july".split('_') -> ["fourth", "of", "july"]
["fourth", "of", "july"].map(&:capitalize) -> ["Fourth", "Of", "July"]
["Fourth", "Of", "July"].join(' ') -> "Fourth Of July"
Staffan answered 17/11, 2016 at 0:51 Comment(3)
def all_supplies_in_holidays(holiday_hash) holiday_hash.each do |seasons, holidays| holidays.each do |holidays, supplies| puts "#{seasons.to_s.capitalize}:" puts " #{holidays.to_s.tr("_"," ").split(' ').map {|word| word.capitalize }.join(' ')}: #{supplies.join(", ")}" end end endShela
I actually did it that way instead of using the "&". What is the purpose of it?Shela
You can use & when mapping over something if the map takes no parameters. It's the same thing as {|i| i.capitalize}, just shorter.Staffan
G
37

In Rails you can use titleize

'fourth_of_july'.titleize => "Fourth Of July"

https://apidock.com/rails/Inflector/titleize

Gagman answered 24/5, 2017 at 10:27 Comment(2)
This is a Rails solutionRobbirobbia
I also like humanize as that only capitalizes the first word rails api docOscaroscillate
S
11

You can use this one liner

str.split('_').map(&:capitalize).join(' ')

This takes a string str and splits it where the underscores are, then capitalizes each word then joins the words together with a space. Example

"fourth_of_july".split('_') -> ["fourth", "of", "july"]
["fourth", "of", "july"].map(&:capitalize) -> ["Fourth", "Of", "July"]
["Fourth", "Of", "July"].join(' ') -> "Fourth Of July"
Staffan answered 17/11, 2016 at 0:51 Comment(3)
def all_supplies_in_holidays(holiday_hash) holiday_hash.each do |seasons, holidays| holidays.each do |holidays, supplies| puts "#{seasons.to_s.capitalize}:" puts " #{holidays.to_s.tr("_"," ").split(' ').map {|word| word.capitalize }.join(' ')}: #{supplies.join(", ")}" end end endShela
I actually did it that way instead of using the "&". What is the purpose of it?Shela
You can use & when mapping over something if the map takes no parameters. It's the same thing as {|i| i.capitalize}, just shorter.Staffan
R
7

I came here looking for a way to modify a string with underscores to be more class-name-like. Rails has String#classify.

irb> 'some_class_string'.classify
=> "SomeClassString"
Roue answered 21/3, 2018 at 16:30 Comment(0)
R
1

Using recursion we can go through your nested hash, find all your keys and apply the change:

def key_changer hash
  hash.map do |k,v|
    [ k.to_s.scan(/[a-zA-Z]+/).map(&:capitalize).join(' '),
      v.class == Hash ? key_changer(v) : v ]
  end.to_h
end

key_changer holiday_dec #=>

#{ "Winter" => { "Christmas"      => ["Lights", "Wreath"],
#                "New Years"      => ["Party Hats"] },
#  "Summer" => { "Fourth Of July" => ["Fireworks", "BBQ"] },
#  "Fall"   => { "Thanksgiving"   => ["Turkey"] },
#  "Spring" => { "Memorial Day"   => ["BBQ"]}
#}

It's not exactly what you asked for (only realised after answering) but I'll leave this answer up nonetheless as you may find it useful.

Rhea answered 17/11, 2016 at 1:35 Comment(0)
A
0
holiday_dec.each_with_object({}) { |(k,v),h|
  h[k] = v.each_with_object({}) { |(kk,vv),g|
    g[kk.to_s.split('_').map { |s| s[0]=s[0].upcase; s }.join(' ')] = vv } }
  #=> {:winter=>{"Christmas"=>["Lights", "Wreath"], "New Years"=>["Party Hats"]},
  #    :summer=>{"Fourth Of July"=>["Fireworks", "BBQ"]},
  #    :fall=>{"Thanksgiving"=>["Turkey"]},
  #    :spring=>{"Memorial Day"=>["BBQ"]}}

I used s[0]=s[0].upcase; s rather than s.capitalize because the latter converts all characters after the first to lower case (as well as capitalizing the first letter), yet the asker didn't say that was desired or if there could be capital letters after the first character of each word.

Armstrong answered 17/11, 2016 at 1:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.