Chapter 7: Hashes
By:
Kushal Jangid
Introduction
A hash is an unordered collection of key-value pairs that
look like this: "storm" => "tornado" . A hash is similar to an
Array , but instead of a default integer index starting at
zero, the indexing is done with keys that can be made up
from any Ruby object
Creating Hashes
You can create an empty hash with the new class method.
months = Hash.new
You can test to see if a hash is empty with empty? :
months.empty? # => true
how big it is with length or size :
months.length
months.size # => 0
Creating Hashes
months = { 1 => "January", 2 => "February", 3 => "March", 4 => "April",
5 => "May", 6 => "June", 7 => "July", 8 => "August", 9 => "September",
10 => "October", 11 => "November", 12 =>"December" }
So far Ive used symbols, integers ( Fixnum s), and strings as keys. You
can use any Ruby object as a key or value, even an array.
Accessing Hashes
zip = { 82442 => "Ten Sleep", 83025 => "Teton Village", 83127 =>"Thayne",
82443 => "Thermopolis", 82084 => "Tie Siding", 82336 => "Tipton",
82240 => "Torrington", 83110 => "Turnerville", 83112 => "Turnerville" }
zip.has_key? 82442 # => true
zip.has_value? "Ten Sleep" # => true
zip[82442] # => "Ten Sleep"
zip.keys # => [83110, 83127, 82336, 83112, 82084, 83025, 82442,
82443, 82240]
zip.values # => ["Turnerville", "Thayne", "Tipton", "Turnerville",
"Tie Siding","Teton Village", "Ten Sleep", "Thermopolis", "Torrington"]
Accessing Hashes
The select method uses a block to
multidimensional array of key - value pairs:
return
zip.select { |key,val| key > 83000 }
#=> [[83110, "Turnerville"], [83127, "Thayne"],
[83112, "Turnerville"], [83025, "Teton Village"]]
new,
Iterating over Hashes
You can iterate over hashes with each , each_key , each_value , or
each_pair . Here are the differences.
The each method calls a block once for each key in a hash, letting
you take a swipe at each pair:
zip.each {|k,v| puts "#{k}/#{v}" }
# =>
83110/Turnerville
83127/Thayne
82336/Tipton
83112/Turnerville
82084/Tie Siding
83025/Teton Village
82442/Ten Sleep
82443/Thermopolis
82240/Torrington
Changing Hashes
rhode_island = { 1 => "Bristol", 2 => "Kent", 3 => "Newport",
4 => "Providence", 5 => "Washington" }
You can use []= to add a pair to this array:
rhode_island[6]= "Dunthorpe"
This adds the value "Dunthorpe" with a key 6 . Or you can use []= to
change a value:
rhode_island[2]= "Bent"
Similarly, you can use the store method to add a pair to the
rhode_island array:
rhode_island.store(6, "Dunthorpe")
Merging Hashes
delaware = { 1 => "Kent", 2 => "New Castle", 3 => "Sussex" }
rhode_island = { 1 => "Bristol", 2 => "Kent", 3 => "Newport",
4 => "Providence", 5 => "Washington" }
rhode_island.merge delaware
# => { 5=>"Washington", 1=>"Kent", 2=>"New Castle", 3=> "Sussex",
4=>"Providence"}
Sorting a Hash
When you sort a hash with the sort method, you get a multidimensional
array of two-element arrays in return.
Comparing Strings
Sometimes you need to test two strings to see if they are the
same or not. You can do that with the == method.
Example:
print "What was the question again?" if question == " "
hay
= "All men are acreated equal."
nicolay = " \"All men are created equal.\" "
hay == nicolay # => false
Comparing Strings
(1). == returns true if two objects are Strings, false otherwise.
(2). eql? returns true if two strings are equal in length and
content, false otherwise.
Yet another way to compare strings is with the <=> method,
commonly called the spaceship operator.
"a" <=> "a" # => 0
A case-insensitive comparison is possible with casecmp.
"a".casecmp "A" # => 0
Manipulating Strings
"A horse! " * 2 # => "A horse! A horse! "
You can concatenate a string to the result:
taf = "That's ".downcase * 3 + "all folks!" # => "that's that's that's all folks!"
taf.capitalize # => "That's that's that's all folks!"
Inserting a String in a String
"Be carful.".insert 6, "e" # => "Be careful."
"Be careful!".insert 3, "very " * 5 # => "Be very very very very very careful!"
"Be careful!".insert 3, "very " # => "Be very careful!"
Changing All or Part of a String
line = "A Porsche! a Porsche! my kingdom for a Porsche!"
cite = "Act V, Scene V"
speaker = "King Richard, 2007"
speaker[", 2007"]= "III" # => "III"
p speaker # => "King Richard III"
cite[13]= "IV" # => "IV"
p cite # => "Act V, Scene IV"
The chomp and chop Methods
The chop (or chop! ) method chops off the last character of a
string, and the chomp ( chomp! ) method chomps off the record
separator ( $/ )usually just a newlinefrom a string.
joe = <<limerick
There once was a fellow named Joe
quite fond of Edgar Allen Poe
He read with delight
Nearly half the night
When his wife said "Get up!" he said "No."
limerick
# => "There once was a fellow named Joe\nquite fond of Edgar Allen
Poe\n He read with delight\n Nearly half the night\nWhen his wife
said \"Get up!\" he said \"No.\"\n"
The chomp and chop Methods
Apply chomp! to remove the last record separator ( \n ):
joe.chomp! # => "There once was a fellow named Joe\nquite fond of Edgar
Allen Poe\n He read with delight\n Nearly half the night\nWhen his wife
said \"Get up!\" he said \"No.\""
joe.chop! = "There once was a fellow named Joe\nquite fond of Edgar
Allen Poe\n He read with delight\n Nearly half the night\nWhen his wife
said \"Get up!\" he said \ "No"
The delete Method
"That's call folks!".delete "c" # => "That's all folks"
"That's alll folks".delete "l" # => "That's a foks"
"That's alll folks".delete "ll" # => "That's a foks"
The nifty thing about this, though, is you can also negate all or part of an
argument with the caret ( ^ ), similar to its use in regular expressions.
"That's all folks".delete "abcdefghijklmnopqrstuvwxyz", "^ha"
# => "haa"
Substitute the Substring
"That's alll folks".gsub "alll", "all" # => "That's all folks"
The replace method replaces a string wholesale. Not just a substring,
the whole thing.
call = "All hands on deck!"
call.replace "All feet on deck!" # => "All feet on deck!"
Turn It Around
"abcdefghijklmnopqrstuvwxyz".reverse
# => "zyxwvutsrqponmlkjihgfedcba"
palindrome = "dennis sinned"
palindrome.reverse! # => "dennis sinned"
p palindrome
From a String to an Array
"0123456789".split # => ["0123456789"]
A regular expression ( // ) that cuts up the original string at the
junction of characters.
"0123456789".split( // ) # => ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
Case Conversion
"Ruby finally has a killer app. It's Ruby on Rails.".capitalize
# => "Ruby finally has a killer app. it's ruby on rails."
Iterating Over a String
The each method ( each_line ) iterates over each separate item, not
just the first word in the overall string, and capitalizes it:
"new\nopen\nclose\nprint".each { |item| puts item.capitalize }
# =>
# New
# Open
# Close
# Print
downcase, upcase, and swapcase
"YOU KNOW IT CAN BE ANNOYING TO READ SOMETHING THAT IS
IN ALL UPPERCASE LETTERS!".downcase
# => "you know it can be annoying to read something that is all in
uppercase letters!
"YOU KNOW IT CAN BE ANNOYING TO READ SOMETHING THAT IS
ALL IN UPPERCASE LETTERS!". downcase.capitalize
# => "You know it can be annoying to read something that is all
in uppercase letters!"
"warning! keyboard may be hot!".upcase
# => WARNING! KEYBOARD MAY BE HOT!
"aAbBcCdDeEfFgGhHiI".swapcase # => "AaBbCcDdEeFfGgHhIi"
Managing Whitespace, etc.
title = "Love's Labours Lost"
title.size # => 19
The added whitespace is calculated based on the length of the string
plus the value of the argument. Watch:
title.ljust 20 # => "Love's Labours Lost "
title.rjust 25 # => "
Love's Labours Lost"
title.rjust( 21, "-" ) # => "--Love's Labours Lost"
title.rjust 25, "->" # => "->->->Love's Labours Lost"
title.rjust(20, "-").ljust(21, "-") # => "-Love's Labours Lost-"
Incrementing Strings
You can increment strings with next and next! (or succ and succ! ).
"a".next [or] "a".succ # => "b"
"z".next # => "aa" # two a's after one z
"zzzz".next # => "aaaaa" # five a's after four z's
"999.0".next # => "999.1" # increment by .1
"999".next # => "1000" # increment from 999 to 1000
Converting Strings
You can convert a string into a float ( Float ) or integer ( Fixnum ).
"200".class # => String
"200".to_f # => 200.0
"200".to_f.class # => Float
"100".class # => String
"100".to_i # => 100
"100".to_i.class # => Fixnum
Thank You